<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-473673253554187747</id><updated>2024-11-01T02:15:17.211-07:00</updated><category term="Android"/><category term="Layout"/><category term="Abuse"/><category term="Accelerometer"/><category term="Animations"/><category term="Camera"/><category term="Consistency"/><category term="Devices"/><category term="Fail"/><category term="LinearLayout"/><category term="Magic"/><category term="RelativeLayout"/><category term="Think Ahead"/><category term="VerticalViewPager"/><title type='text'>Martin Sonc</title><subtitle type='html'>Android Guy</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://martinsonc.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://martinsonc.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11056772522189154527</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-473673253554187747.post-1517138153230562698</id><published>2013-04-23T14:42:00.000-07:00</published><updated>2013-06-05T09:33:44.587-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="VerticalViewPager"/><title type='text'>Android VerticalViewPager</title><content type='html'>&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9EZ_827IHG2dN0DuOTdjGqva47Ov9PCA4UV5QiEnExkklT67Blc5D7fpQMe_f1GmGss6uJglVciMOqaB-ekj1nxbos6mO3KKQnpTmw-TTsEZ6XQHC9YWiAcuQkGpmjlZ17Bg9UZQoRCs/s1600/google_android_robot-wallpaper-480x272.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;180&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9EZ_827IHG2dN0DuOTdjGqva47Ov9PCA4UV5QiEnExkklT67Blc5D7fpQMe_f1GmGss6uJglVciMOqaB-ekj1nxbos6mO3KKQnpTmw-TTsEZ6XQHC9YWiAcuQkGpmjlZ17Bg9UZQoRCs/s320/google_android_robot-wallpaper-480x272.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;I&#39;ve spent the last couple of months working on a project that required an implementation of the native&amp;nbsp;&lt;a class=&quot;g-profile&quot; href=&quot;http://plus.google.com/104629412415657030658&quot; target=&quot;_blank&quot;&gt;+Android&lt;/a&gt;&amp;nbsp;ViewPager that would support vertical paging. And since Google went blind I&#39;ve decided to &lt;i&gt;simply&lt;/i&gt; update the native ViewPager code. Naturally it wasn&#39;t that &lt;i&gt;simple&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Fortunately, I am able to share the final code with the world this time, so head over to &lt;a href=&quot;https://github.com/LambergaR/VerticalViewPager&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt;&amp;nbsp;and check it out. The implementation is completely the same as for the native &lt;a href=&quot;http://developer.android.com/reference/android/support/v4/view/ViewPager.html&quot; target=&quot;_blank&quot;&gt;ViewPager&lt;/a&gt;, so no surprises there.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;background-color: white; line-height: 18px;&quot;&gt;There&#39;s one bug I&#39;ve managed to find. I can&#39;t for the life of me get the bottom &amp;nbsp;&lt;a href=&quot;http://developer.android.com/reference/android/support/v4/widget/EdgeEffectCompat.html&quot; target=&quot;_blank&quot;&gt;EdgeEffectCompat&lt;/a&gt; (the blueish edge effect when reaching the last page) to render, so,&amp;nbsp;&lt;a class=&quot;g-profile&quot; href=&quot;http://plus.google.com/108967384991768947849&quot; target=&quot;_blank&quot;&gt;+Android Developers&lt;/a&gt;,&amp;nbsp;feel free to fix the damn thing :)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br style=&quot;background-color: white; line-height: 18px;&quot; /&gt;&lt;span style=&quot;background-color: white; line-height: 18px;&quot;&gt;To see the problematic code check out lines &lt;a href=&quot;https://github.com/LambergaR/VerticalViewPager/blob/master/src/VerticalViewPager.java#L2155&quot; target=&quot;_blank&quot;&gt;2155-2168 in VerticalViewPager.java&lt;/a&gt;.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
If you manage to fix the bug or would like to recommend (or even better, implement) some improvements just leave a comment or find me on &lt;a href=&quot;https://plus.google.com/107777704046743444096&quot; target=&quot;_blank&quot;&gt;G+&lt;/a&gt;.&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
</content><link rel='replies' type='application/atom+xml' href='http://martinsonc.blogspot.com/feeds/1517138153230562698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/473673253554187747/1517138153230562698' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/1517138153230562698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/1517138153230562698'/><link rel='alternate' type='text/html' href='http://martinsonc.blogspot.com/2013/04/android-vertical-view-pager.html' title='Android VerticalViewPager'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11056772522189154527</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9EZ_827IHG2dN0DuOTdjGqva47Ov9PCA4UV5QiEnExkklT67Blc5D7fpQMe_f1GmGss6uJglVciMOqaB-ekj1nxbos6mO3KKQnpTmw-TTsEZ6XQHC9YWiAcuQkGpmjlZ17Bg9UZQoRCs/s72-c/google_android_robot-wallpaper-480x272.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-473673253554187747.post-5176887064715198839</id><published>2012-12-08T21:04:00.000-08:00</published><updated>2012-12-08T21:06:21.088-08:00</updated><title type='text'>Android bug reports on the go</title><content type='html'>&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;
We&#39;re all usually testing our applications all the time and discover the weirdest bugs while being far away from our computer with no real way to see what happened. All we can do is hope that we&#39;ll be able to reproduce the issue when we get to the computer.&lt;br /&gt;
&lt;br /&gt;
Not any more!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
With Android 4.2 an amazing option called &lt;b&gt;Power menu bug report&lt;/b&gt;&amp;nbsp;was added. Simply turn on the option in the &lt;b&gt;Developer options&lt;/b&gt;&amp;nbsp;menu and long-press the power button when you encounter an issue. A new option called &lt;b&gt;Bug report&lt;/b&gt;&amp;nbsp;will appear.&amp;nbsp;The system will generate a report (it really can take a while and there is no progress indicator, so just be patient). When complete you will be presented with the &lt;b&gt;Complete action using&lt;/b&gt;&amp;nbsp;dialog where you should select the Gmail option for best results.&lt;br /&gt;
&lt;br /&gt;
When the email arrives to your inbox there will be two files attached - the screenshot (really good idea!) and a &lt;b&gt;bugreport-*.txt&lt;/b&gt; file containing one of the most complete system dumps I&#39;ve ever seen. Most of you will probably be looking for the section labeled&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;&lt;b&gt;&lt;i&gt;------ SYSTEM LOG (logcat -v threadtime -d *:v) ------&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;&lt;b&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Happy debugging! :)&lt;/span&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC6yl3kfnihLFjWfWH_iYiGwAZKP6yjE5GvNj6s9_X6oXwfvJfy4G1aGlzRbNBgUeiF-npU_EkmaH81KQs2sNeYmyv9V9xmmgkRsqvF7n1Hh57YCXVTjSykzLbBM-ZVpLN8o0LywNcxbw/s1600/Screenshot_2012-12-08-20-27-31.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC6yl3kfnihLFjWfWH_iYiGwAZKP6yjE5GvNj6s9_X6oXwfvJfy4G1aGlzRbNBgUeiF-npU_EkmaH81KQs2sNeYmyv9V9xmmgkRsqvF7n1Hh57YCXVTjSykzLbBM-ZVpLN8o0LywNcxbw/s320/Screenshot_2012-12-08-20-27-31.png&quot; width=&quot;180&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8UkwHwMcpeOQZPRVdAmMNYDQHyFKI6Mfpv9cd_GCIFcbGy_7Z_GWNPB1Ci8XCB-vcmxKi4QBAOa9tJ-aLZfPCbALkPWuqZwzLvzQWRRI7WucsUPUQynEh51k3OvVUJyQTkGvKFoHS8nI/s1600/Screenshot_2012-12-08-20-28-17.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8UkwHwMcpeOQZPRVdAmMNYDQHyFKI6Mfpv9cd_GCIFcbGy_7Z_GWNPB1Ci8XCB-vcmxKi4QBAOa9tJ-aLZfPCbALkPWuqZwzLvzQWRRI7WucsUPUQynEh51k3OvVUJyQTkGvKFoHS8nI/s320/Screenshot_2012-12-08-20-28-17.png&quot; width=&quot;180&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://martinsonc.blogspot.com/feeds/5176887064715198839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/473673253554187747/5176887064715198839' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/5176887064715198839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/5176887064715198839'/><link rel='alternate' type='text/html' href='http://martinsonc.blogspot.com/2012/12/android-bug-reports-on-go.html' title='Android bug reports on the go'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11056772522189154527</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC6yl3kfnihLFjWfWH_iYiGwAZKP6yjE5GvNj6s9_X6oXwfvJfy4G1aGlzRbNBgUeiF-npU_EkmaH81KQs2sNeYmyv9V9xmmgkRsqvF7n1Hh57YCXVTjSykzLbBM-ZVpLN8o0LywNcxbw/s72-c/Screenshot_2012-12-08-20-27-31.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-473673253554187747.post-3356983501184524571</id><published>2012-12-02T16:55:00.002-08:00</published><updated>2012-12-02T17:00:27.551-08:00</updated><title type='text'>Running ADB over WiFi</title><content type='html'>Just a quick hint for everyone that would like to get rid of all the USB cables between your computer and the Android device you&#39;re testing your applications on. There&#39;s a simple way to persuade the ADB to run over WiFi without having to have root access to your device.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;connect the device to your computer using the USB cable&lt;/li&gt;
&lt;li&gt;launch the terminal and locate your adb file (android-sdk/platform-tools/)&lt;/li&gt;
&lt;li&gt;figure out the IP address that&#39;s assigned to your device&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
settings / Wi-Fi / advanced&amp;nbsp;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;run the following commands (don&#39;t forget to replace &lt;b&gt;[IP]&lt;/b&gt; with the IP you found in the previous step):&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
adb tcpip 5555&lt;br /&gt;
adb connect &lt;b&gt;[IP]&lt;/b&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;unplug the device and enjoy the world of wireless&lt;/li&gt;
&lt;li&gt;to enable USB debugging again just run the following command&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
adb usb&lt;/blockquote&gt;
</content><link rel='replies' type='application/atom+xml' href='http://martinsonc.blogspot.com/feeds/3356983501184524571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/473673253554187747/3356983501184524571' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/3356983501184524571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/3356983501184524571'/><link rel='alternate' type='text/html' href='http://martinsonc.blogspot.com/2012/12/running-adb-over-wifi.html' title='Running ADB over WiFi'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11056772522189154527</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-473673253554187747.post-3543717133174462285</id><published>2012-09-17T18:40:00.001-07:00</published><updated>2012-09-17T18:40:08.332-07:00</updated><title type='text'>Android, Calendar and Time Zones</title><content type='html'>Let&#39;s say you&#39;re building a time tracking app and want it to work for users that travel a lot. Simple, you say, just store the timezone value and move on.&lt;br /&gt;
&lt;br /&gt;
Well, you might want to do some testing before that.&lt;br /&gt;
&lt;br /&gt;
There are two ways to set the timezone in a Calendar object:&lt;br /&gt;
&lt;br /&gt;
&lt;iframe src=&quot;http://pastebin.com/embed_iframe.php?i=4Fuu4Afu&quot; style=&quot;border: none; height: 192px; width: 100%;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
Both of them are supposed to work, but unfortunately the option one only works on Android versions up to 2.2 and option two only works on Android versions 2.2+. The simple solution is to simple set both values and voila - everything is working.&lt;br /&gt;
&lt;br /&gt;
Oh, and another thing ... &lt;b&gt;c.clear()&lt;/b&gt;&amp;nbsp;does &lt;i&gt;not &lt;/i&gt;clear the timezone value. Ever.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Android Calendar Madness.</content><link rel='replies' type='application/atom+xml' href='http://martinsonc.blogspot.com/feeds/3543717133174462285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/473673253554187747/3543717133174462285' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/3543717133174462285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/3543717133174462285'/><link rel='alternate' type='text/html' href='http://martinsonc.blogspot.com/2012/09/android-calendar-and-time-zones.html' title='Android, Calendar and Time Zones'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11056772522189154527</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-473673253554187747.post-2902936501635932555</id><published>2012-08-14T20:04:00.000-07:00</published><updated>2012-08-14T20:06:18.966-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Abuse"/><category scheme="http://www.blogger.com/atom/ns#" term="Accelerometer"/><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Consistency"/><title type='text'>Android Accelerometer Madness</title><content type='html'>&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: left; margin-right: 1em; text-align: left;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjES0ze1YFCOkPPbUv_Y_7MmJU_yP9LFW2TPhaKY4F2XnIlbCLbup_rbWurK3AfK7wrzDdptkCMIJ5BOkPm9GWDv34ZDpEFgurhpP0HaP-io-ZtNeyVQZz_62nZXEIckMmrUkWjet9zWKQ/s1600/chris-flanagan-acceleration%5B1%5D.jpeg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjES0ze1YFCOkPPbUv_Y_7MmJU_yP9LFW2TPhaKY4F2XnIlbCLbup_rbWurK3AfK7wrzDdptkCMIJ5BOkPm9GWDv34ZDpEFgurhpP0HaP-io-ZtNeyVQZz_62nZXEIckMmrUkWjet9zWKQ/s320/chris-flanagan-acceleration%5B1%5D.jpeg&quot; width=&quot;240&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://motion-forces-and-energy.wikispaces.com/file/view/chris-flanagan-acceleration%5B1%5D.jpg/141788017/chris-flanagan-acceleration%5B1%5D.jpg&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;via wikispaces.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
I&#39;m definitely willing to admit that we&#39;re not always using some mobile device&#39;s functionality as originally intended at&amp;nbsp;&lt;a href=&quot;http://azumio.com/&quot; target=&quot;_blank&quot;&gt;Azumio&lt;/a&gt;, but we sure would appreciate some consistency across different Android devices. The previous sensor we decided to (ab)use was camera, which is still causing some sleepless nights with new and weird phone coming out quite regularly - you can read all about it in the&amp;nbsp;&lt;a href=&quot;http://martinsonc.blogspot.com/2012/01/android-camera-madness.html&quot; target=&quot;_blank&quot;&gt;Android Camera Madness&lt;/a&gt;&amp;nbsp;post. This time we&#39;re trying to develop an app using the accelerometer, a really useful sensor embedded in every(?) Android device.&lt;br /&gt;
&lt;br /&gt;
So, here&#39;s the story.&lt;br /&gt;
&lt;br /&gt;
We need to monitor the movement during an extended period of time, which also means we need to get events in background. Which should not be problematic and easily solvable with a right combination of&amp;nbsp;&lt;a href=&quot;http://developer.android.com/reference/android/app/Service.html&quot; target=&quot;_blank&quot;&gt;Services&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href=&quot;http://developer.android.com/reference/android/os/PowerManager.WakeLock.html&quot; target=&quot;_blank&quot;&gt;WakeLocks&lt;/a&gt;. And, on some phones (for instance, &lt;a href=&quot;http://www.google.com/nexus/#/galaxy&quot; target=&quot;_blank&quot;&gt;GalaxyNexus&lt;/a&gt;&amp;nbsp;can handle everything as expected). Unfortunately the other more popular Samsung devices are not that reliable. I&#39;ve soon realized that we&#39;re gonna need some more black magic to make it work on Galaxy SII and Galaxy SIII that share a similar problem - when the screen is turned off accelerometer stops propagating the data.&lt;br /&gt;
&lt;br /&gt;
Fortunately, the solution seems to be quite simple, all you need to do is listen to the &lt;a href=&quot;http://developer.android.com/reference/android/content/Intent.html#ACTION_SCREEN_OFF&quot; target=&quot;_blank&quot;&gt;ACTION_SCREEN_OFF&lt;/a&gt;&amp;nbsp;broadcast and restart the accelerometer. Except, it&#39;s not that simple.&lt;br /&gt;
&lt;br /&gt;
There are two more things that you need to be careful about:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;allow some delay between the ACTION_SCREEN_OFF broadcast (1-2s seem to be just enough)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;never&lt;/b&gt;&amp;nbsp;do that on a phone that works as expected (so using, Service + &lt;a href=&quot;http://developer.android.com/reference/android/os/PowerManager.html#PARTIAL_WAKE_LOCK&quot; target=&quot;_blank&quot;&gt;Partial Wake Lock&lt;/a&gt;) when the screen is off&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
What we ended up doing is again, fairly simple when you figure it out:&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;listen for ACTION_SCREEN_OFF broadcast&lt;/li&gt;
&lt;li&gt;check if you have the WakeLock and re-acquire it if needed&lt;/li&gt;
&lt;li&gt;raise a sample counting flag and start counting samples&amp;nbsp;&lt;/li&gt;
&lt;li&gt;post a &lt;a href=&quot;http://developer.android.com/reference/java/lang/Runnable.html&quot; target=&quot;_blank&quot;&gt;Runnable&lt;/a&gt; to a &lt;a href=&quot;http://developer.android.com/reference/android/os/Handler.html&quot; target=&quot;_blank&quot;&gt;Handler&lt;/a&gt; via the &lt;a href=&quot;http://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable, long)&quot; target=&quot;_blank&quot;&gt;postDelayed&lt;/a&gt; method that checks the counter (be careful, the Accelerometer might have sent some events after the screen was off - 5s timer and 100 samples seem to work)&lt;/li&gt;
&lt;li&gt;check if you got any samples. If yes - you&#39;re good to go, just stop here&lt;/li&gt;
&lt;li&gt;restart the algorithm&lt;/li&gt;
&lt;li&gt;repeat 1-4 to confirm if it works&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
You need to be careful not to take any results as a guarantee that it will work the next time the screen is turned off, I&#39;ve noticed that some phones are turning off the damn thing on random.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
On some devices even that might not work, so the best you can do is display a warning and let the user decide if he wants to run the app with a full wake lock (you can dimm the screen, but never turn it off).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://martinsonc.blogspot.com/feeds/2902936501635932555/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/473673253554187747/2902936501635932555' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/2902936501635932555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/2902936501635932555'/><link rel='alternate' type='text/html' href='http://martinsonc.blogspot.com/2012/08/android-accelerometer-madness.html' title='Android Accelerometer Madness'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11056772522189154527</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjES0ze1YFCOkPPbUv_Y_7MmJU_yP9LFW2TPhaKY4F2XnIlbCLbup_rbWurK3AfK7wrzDdptkCMIJ5BOkPm9GWDv34ZDpEFgurhpP0HaP-io-ZtNeyVQZz_62nZXEIckMmrUkWjet9zWKQ/s72-c/chris-flanagan-acceleration%5B1%5D.jpeg" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>Palo Alto, CA, USA</georss:featurename><georss:point>37.4418834 -122.1430195</georss:point><georss:box>37.3410269 -122.30094799999999 37.5427399 -121.985091</georss:box></entry><entry><id>tag:blogger.com,1999:blog-473673253554187747.post-1551349499677396955</id><published>2012-01-28T23:07:00.000-08:00</published><updated>2012-01-28T23:15:14.813-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Camera"/><category scheme="http://www.blogger.com/atom/ns#" term="Devices"/><category scheme="http://www.blogger.com/atom/ns#" term="Magic"/><title type='text'>Android Camera Madness</title><content type='html'>&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: left; margin-right: 1em; text-align: left;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://media.tested.com/uploads/0/5/9503-4357_htc_cameraphone_super.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;171&quot; src=&quot;http://media.tested.com/uploads/0/5/9503-4357_htc_cameraphone_super.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://media.tested.com/uploads/0/5/9503-4357_htc_cameraphone_super.jpg&quot;&gt;image: tested.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Camera in Android works, and it works well - as long as you don&#39;t try to do something a bit more complicated than taking photos and shooting videos. Anything more soon reveals some flaws in the implementation.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
In &lt;a href=&quot;https://market.android.com/details?id=com.azumio.instantheartrate.full&quot;&gt;Instant Heart Rate&lt;/a&gt; we are doing some heavy processing of images taken by the camera and we would expect some consistency across Camera implementation across different devices and Android OS versions out there. Unfortunately, that&#39;s not the case.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Let&#39;s start with the flashlight&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
When user starts the measurement we turn on the flashlight to provide enough light to see &quot;inside&quot; your finger. We clearly tell them that the results might be lower in quality on devices without flash, and would provide a reliable result on the rest of devices. But, what do you tell the user when device has the flashlight, but the manufacturer decided (I would rather say forgot) not to allow the applications to turn on the flashlight when needed? We are seing this problems on a few new devices, that have a lower price that makes them easily affordable and do as such have a quite large number of users. Here comes the first round of one star reviews&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Frame rate&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
We require a high frame rate to get the best results. We have even optimized the algorithm to handle lower frame rates (as a workaround for some older Motorola devices). But, what do we do when:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;device ignores the frame rate that you set (even when the frame rate is one of the ones device reported as supported)&lt;/li&gt;
&lt;li&gt;device crashes when you try to set the frame rate&lt;/li&gt;
&lt;li&gt;device changes the frame rate during the measurement (again, without providing a way to retrieve the new value)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
It gets even worst, when you combine it with the next issue.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Time stamps&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
When camera captures the frame it is sent to the application via a callback. Since the camera is not running on UI thread, there is a time difference between the actual capture time and the time the frame arrived to the application.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
But, since we are expecting the UI thread to occasionally get blocked with animations, layout updates and all the other Android Layout nonsense (since nothing is rendered on GPU) we provide the camera a little buffer so we get all the captured frames for processing. The buffer size is calculated according to preview sizes available on the device since we do not have a big chunk of memory available for allocation (for instance and as some devices only provide&amp;nbsp;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;640x480 or even &lt;/span&gt;800x600 preview sizes we can sometimes afford only one or two.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
And since no time stamp is associated with the frame returned to the application, we have no obvious way of knowing, when the frame was taken - we can only make a fairly well educated assumption. Let me try to illustrate this with an example:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
In this case, the camera has reported a frame rate of 30 fps and we can buffer max 3 frames.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
T = difference in time when the frame was returned to the application from the previous frame&lt;/div&gt;
&lt;div&gt;
# = number of the frame&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp;# | &amp;nbsp;T &amp;nbsp;| &amp;nbsp;? &amp;nbsp;| &amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;---|-----|-----|&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp;1 | 0 &amp;nbsp; | &amp;nbsp;0 &amp;nbsp;|&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp;2 | 30 &amp;nbsp;| &amp;nbsp;0 &amp;nbsp;|&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp;3 | 30 &amp;nbsp;| &amp;nbsp;0 &amp;nbsp;| &amp;nbsp;all okay, steady frame rate&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp;4 | 40 &amp;nbsp;| +10 | &amp;nbsp;huh, what happened here?&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp;5 | 50 &amp;nbsp;| +20 | &amp;nbsp;ok, UI thread is busy, the frames are delayed&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp;6 | 50 &amp;nbsp;| +20 | &amp;nbsp;so, the delay is now 50ms, 1 buffer is taken&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp;7 | 70 &amp;nbsp;| +40 | &amp;nbsp;the buffer is full. next lost frame is discarded&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp;8 | 10 &amp;nbsp;| -20 | &amp;nbsp;huh, one buffer got processed, yay&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp;9 | 50 &amp;nbsp;| +20 |&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;10 | 40 &amp;nbsp;| +10 | &amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;11 | 60 &amp;nbsp;| +30 | &amp;nbsp;and here we are, we just lost a frame&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;So, we can be creative and put a modified timestamp to a frame using the logic illustrated above. And it works really good, as long as the camera maintains the frame rate. But, some cameras are being smart about it without providing any pointers to when it happened and what the black magic actually made. They detect dropped frames and modify the frame rate so the number of lost frames is as low as possible - and since the frame rate sent to the camera or the frame rate the camera is returning, that is only a hint. &lt;b&gt;A hint!&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Native access&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
It turns of that Android knows when the image was taken. It just gets lost with all the levels of abstraction. So, in theory we could just write the algorithm in C/C++ and get the native Camera interface. And the code would run much faster too! So, we have a solution to our problem. Oh, wait, no we don&#39;t. The native Camera implementation is considered a &lt;b&gt;private API&lt;/b&gt;&amp;nbsp;and the camera API has changed with every single major Android release and is different across the devices since manufacturers tend to write their own implementations. So, we would need to provide an implementation for all the major releases, all the devices and the code would most likely break with every new Android version or Android device.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Magical devices&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;
Last but not least - there are some devices that are best described to be magical. Rooted devices and devices with custom ROMs are a majority, but are far from being the only devices that are a bit special.&lt;br /&gt;
&lt;br /&gt;
Some custom ROMs do not have a Camera implemented, so it&#39;s a bit unrealistic expecting from us to support them. Fortunately, this seems to be limited only to devices with no access to Android market, so we don&#39;t really care.&lt;br /&gt;
&lt;br /&gt;
Then there are devices, that throw a &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;NullPointerException&lt;/span&gt; when you try to get the Camera object. Or others, that are throwing weird exception when you try to get a property from a Camera object:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;white-space: pre-wrap; word-wrap: break-word;&quot;&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&quot;java.lang.NullPointerException&quot;,           &amp;nbsp;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style=&quot;white-space: pre-wrap; word-wrap: break-word;&quot;&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&quot;android.hardware.Camera$Parameters.getSupportedPictureFormats(Camera.java:1721)&quot;,&lt;/span&gt;&lt;/pre&gt;
&lt;pre style=&quot;white-space: pre-wrap; word-wrap: break-word;&quot;&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;pre style=&quot;word-wrap: break-word;&quot;&gt;&lt;span style=&quot;font-family: Times;&quot;&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;Or some, that can&#39;t even parse their own properties without choking on them:&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style=&quot;word-wrap: break-word;&quot;&gt;&lt;span style=&quot;font-family: Times;&quot;&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style=&quot;word-wrap: break-word;&quot;&gt;&lt;pre style=&quot;white-space: pre-wrap; word-wrap: break-word;&quot;&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&quot;java.lang.NumberFormatException: unable to parse &#39;null&#39; as integer&quot;,
&quot;unable to parse &#39;null&#39; as integer&quot;,
&quot;java.lang.Integer.parseInt(Integer.java:347)&quot;,
&quot;java.lang.Integer.parseInt(Integer.java:323)&quot;,
&quot;android.hardware.Camera$Parameters.getInt(Camera.java:905)&quot;,                &quot;android.hardware.Camera$Parameters.getJpegThumbnailQuality(Camera.java:979)&quot;,&lt;/span&gt;&lt;/pre&gt;
&lt;/pre&gt;
&lt;pre style=&quot;word-wrap: break-word;&quot;&gt;&lt;span style=&quot;font-family: Times;&quot;&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style=&quot;word-wrap: break-word;&quot;&gt;&lt;span style=&quot;font-family: Times;&quot;&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;Oh, and from time to time the Camera service simply dies and there&#39;s no other way to get it up and running but to restart your phone.&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style=&quot;word-wrap: break-word;&quot;&gt;&lt;span style=&quot;font-family: Times;&quot;&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style=&quot;word-wrap: break-word;&quot;&gt;&lt;span style=&quot;font-family: Times;&quot;&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style=&quot;word-wrap: break-word;&quot;&gt;&lt;span style=&quot;font-family: Times;&quot;&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style=&quot;word-wrap: break-word;&quot;&gt;&lt;span style=&quot;font-family: Times;&quot;&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
So do what we can, we are being as creative as possible and try to support every device out there, but sometimes our hands are just tied and we are stuck at a dead end.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinsonc.blogspot.com/feeds/1551349499677396955/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/473673253554187747/1551349499677396955' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/1551349499677396955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/1551349499677396955'/><link rel='alternate' type='text/html' href='http://martinsonc.blogspot.com/2012/01/android-camera-madness.html' title='Android Camera Madness'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11056772522189154527</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total><georss:featurename>Palo Alto, CA, USA</georss:featurename><georss:point>37.4418834 -122.1430195</georss:point><georss:box>37.3410269 -122.30094799999999 37.5427399 -121.985091</georss:box></entry><entry><id>tag:blogger.com,1999:blog-473673253554187747.post-591537682490831609</id><published>2011-10-24T23:42:00.000-07:00</published><updated>2011-10-25T00:17:44.489-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Animations"/><category scheme="http://www.blogger.com/atom/ns#" term="Fail"/><category scheme="http://www.blogger.com/atom/ns#" term="Layout"/><category scheme="http://www.blogger.com/atom/ns#" term="Think Ahead"/><title type='text'>&quot;Now do the animations&quot;</title><content type='html'>&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: right; margin-left: 1em; text-align: right;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKMxuNu8nTwi78YHNwwFlGjXIzwBwuyIiAYQUFgV1au6uIqjGLruNb00QSnijCrAUBH7bPYHLkyi6PeLji76mX1Ir5zrvYqJtR7_bWppJIhbXwOJHiOc5rPo-46hEr05dfNcek4Y0iRx0/s1600/4821316259_d5e8414cba_m.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKMxuNu8nTwi78YHNwwFlGjXIzwBwuyIiAYQUFgV1au6uIqjGLruNb00QSnijCrAUBH7bPYHLkyi6PeLji76mX1Ir5zrvYqJtR7_bWppJIhbXwOJHiOc5rPo-46hEr05dfNcek4Y0iRx0/s1600/4821316259_d5e8414cba_m.jpg&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;(cc)&amp;nbsp;&lt;a href=&quot;http://www.flickr.com/photos/tarabrown/&quot;&gt;tarabrown&lt;/a&gt;&amp;nbsp;via&amp;nbsp;&lt;a href=&quot;http://www.flickr.com/&quot;&gt;Flickr&lt;/a&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
I made a mistake.&lt;br /&gt;
&lt;br /&gt;
There was a new app to write, designs all ready, waiting for me to dig in. So, naturally I took a few hours to go trough the whole thing, pen and paper technique, trying to figure out how to translate the designer&#39;s idea to an actual product.&lt;br /&gt;
&lt;br /&gt;
Ok, done, time to open Photoshop and enter the world of pain (no surprise here, I hate PS, I find it extremely counterintuitive and bloated). First screen done, supporting all the resolutions, yummy, now translate the whole thing to Android Layout XML, another pleasant process. A week or two later, there was a beautiful app just waiting to be shown to the world.&lt;br /&gt;
&lt;br /&gt;
Here it comes, the &#39;I&amp;nbsp;fail&#39; part of the post.&lt;br /&gt;
&lt;br /&gt;
&quot;Nice job. &lt;b&gt;Now do the animations&lt;/b&gt;.&quot;&lt;br /&gt;
&lt;br /&gt;
And let me tell you, if your layout was not created to accomodate the animations from day one you&#39;re pretty much screwed. With all the relativity involved in the product I got a layout that can adopt to any Android phone&#39;s screen size, a must in the Android world, but it animation wise - a big no-go.&lt;br /&gt;
&lt;br /&gt;
Let me just give you an example. Below the header part the application there is a fade to transparent part of the view, covering the top few pixels of the scrolling view under it. So, I did the following:&lt;br /&gt;
&lt;br /&gt;
&lt;iframe src=&quot;http://pastebin.com/embed_iframe.php?i=j7AxM6MB&quot; style=&quot;border: none; width: 100%;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
Simple enough. But try to animate the header and gradient to&amp;nbsp;seamlessly&amp;nbsp;slide of the top of the screen at the same time. No way!&lt;br /&gt;
&lt;br /&gt;
I&#39;m still working on it. And I have learned my lesson.</content><link rel='replies' type='application/atom+xml' href='http://martinsonc.blogspot.com/feeds/591537682490831609/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/473673253554187747/591537682490831609' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/591537682490831609'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/591537682490831609'/><link rel='alternate' type='text/html' href='http://martinsonc.blogspot.com/2011/10/android-layout-animations-or-i-made.html' title='&quot;Now do the animations&quot;'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11056772522189154527</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKMxuNu8nTwi78YHNwwFlGjXIzwBwuyIiAYQUFgV1au6uIqjGLruNb00QSnijCrAUBH7bPYHLkyi6PeLji76mX1Ir5zrvYqJtR7_bWppJIhbXwOJHiOc5rPo-46hEr05dfNcek4Y0iRx0/s72-c/4821316259_d5e8414cba_m.jpg" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>Palo Alto, CA 94301, USA</georss:featurename><georss:point>37.4418834 -122.1430195</georss:point><georss:box>37.3410269 -122.30094799999999 37.5427399 -121.985091</georss:box></entry><entry><id>tag:blogger.com,1999:blog-473673253554187747.post-3641206057987013439</id><published>2011-10-03T23:53:00.000-07:00</published><updated>2011-10-24T23:42:57.029-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Layout"/><category scheme="http://www.blogger.com/atom/ns#" term="LinearLayout"/><category scheme="http://www.blogger.com/atom/ns#" term="RelativeLayout"/><title type='text'>Fine Tuning Android Layouts</title><content type='html'>One of the main&amp;nbsp;differentiators in mobile app market is the final polish of the application. There are many applications available providing really awesome functionality but most of them are lacking the magic &lt;b&gt;Final Polish&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Being a developer I have to constantly reming myself that I am not coding for fellow programmers, but for the end user, some John Doe that wants the application not only to work perfectly, but expects it to have good and easy user interface, just the appropriate amount of rich graphics and to top it off some nice animations that guide him trough the app. And Android is not much help with that.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkKMpIskKjbLHipg-wuPEwnWVSc2AT_utwuSFuL7AS78bIU3hJHKX1GjIDs2-XYS54mWhdMNkBux83D0gkKCEyiez_dteAbBFfmpZFatJj-AS3PD2P8zmAbKgDNqDJVtk0gsKKfQMAFUE/s1600/ss-320-0-4.jpeg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkKMpIskKjbLHipg-wuPEwnWVSc2AT_utwuSFuL7AS78bIU3hJHKX1GjIDs2-XYS54mWhdMNkBux83D0gkKCEyiez_dteAbBFfmpZFatJj-AS3PD2P8zmAbKgDNqDJVtk0gsKKfQMAFUE/s400/ss-320-0-4.jpeg&quot; width=&quot;266&quot; /&gt;&lt;/a&gt;One of the most recent projects I have been involved with,&amp;nbsp;&lt;a href=&quot;https://market.android.com/details?id=si.modula.android.instantheartrate&quot;&gt;Instant Heart Rate&lt;/a&gt;, features a rather rich, circular interface positioned in the center of the screen. Being a bit different that most android applications, the code creating the layout is a bit of a ... well, mess.&lt;br /&gt;
&lt;br /&gt;
The effort that was put into making this thing look and feel right was quite big, and I am sometimes wondering if it was worth it. Implementing a more linear, square-ish design would be much easier and would provide a similar experience. Similar, but not the same.&lt;br /&gt;
&lt;br /&gt;
Some developers would argue that all the problems would go away if Android would have&amp;nbsp;a proper &lt;a href=&quot;http://en.wikipedia.org/wiki/WYSIWYG&quot;&gt;WYSWYG&lt;/a&gt;&amp;nbsp;editor, but I would agree that we &lt;a href=&quot;http://designbycode.tumblr.com/post/1079612795/why-dont-wysiwyg-android&quot;&gt;don&#39;t really want one&lt;/a&gt;. Not only does this weird XML syntax encourages you to optimize the layout, it also forces you to think about all the different screen sizes Android has to offer. And after coding for Android for about three years now, &lt;a href=&quot;http://developer.android.com/reference/android/widget/RelativeLayout.html&quot;&gt;RelativeLayout&lt;/a&gt;&amp;nbsp;and &amp;nbsp;&lt;a href=&quot;http://developer.android.com/reference/android/graphics/NinePatch.html&quot;&gt;NinePatch&lt;/a&gt; images have become two of my best friends. And I am quite surprised to have met several Android developers that have never herd of those. Oh, and yes, &lt;a href=&quot;http://developer.android.com/reference/android/widget/AbsoluteLayout.html&quot;&gt;AbsoluteLayout&lt;/a&gt;&amp;nbsp;is finally marked as deprecated!&lt;br /&gt;
&lt;br /&gt;
Another poorly documented but really interesting option available in the &lt;a href=&quot;http://developer.android.com/guide/topics/ui/layout-objects.html#linearlayout&quot;&gt;LinearLayout&lt;/a&gt; is the weight parameter, enabling you to &quot;assign an &#39;importance&#39; value to a view&quot;.&lt;br /&gt;
&lt;br /&gt;
If you are singing &quot;&lt;a href=&quot;http://www.youtube.com/watch?v=d0vXxH1IEmQ#t=32s&quot;&gt;A little less conversation&lt;/a&gt;&quot; by now let me show you some code in action.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: large;&quot;&gt;Simple Useless Example #1&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;iframe src=&quot;http://pastebin.com/embed_iframe.php?i=tUiGSZsc&quot; style=&quot;border: none; width: 80%;&quot;&gt;&lt;/iframe&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
Pretty simple, straight forward approach, working on all devices and on all orientations. As you can see, the first &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;ImageView&lt;/span&gt; element has the &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;weight&lt;/span&gt; parameter set to 1 and the second to 2, making the first one &lt;b&gt;less important by 1 &lt;/b&gt;&#39;point&#39;. The &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;TextView&lt;/span&gt; added later is positioned above the LinearLayout,&amp;nbsp;producing the following result:&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ54BcYeZdz8znD4GQEUnGSGPKpa72YDFRjET2VZ8RV_1iiGtNsuQB3lVvEO-gWmvya1p4e5RVqjdTdLvOC6Z-_V8PpTEjGKn6OfcrpIP6LLCVG99NBuaGTvfZuZJvJ-pFny8VdFfFaCM/s1600/Screen+Shot+2011-10-04+at+12.41.04+AM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;144&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ54BcYeZdz8znD4GQEUnGSGPKpa72YDFRjET2VZ8RV_1iiGtNsuQB3lVvEO-gWmvya1p4e5RVqjdTdLvOC6Z-_V8PpTEjGKn6OfcrpIP6LLCVG99NBuaGTvfZuZJvJ-pFny8VdFfFaCM/s320/Screen+Shot+2011-10-04+at+12.41.04+AM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
While this is a pretty trivial example it produces perfect results on every screen and orientation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: large;&quot;&gt;&lt;br /&gt;Simple Useless Example #2&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuzit3-41mx3eREU9kSuHvSZ9KVQkbYuUD8gCnfyDNt5-tTg76ytYVu6xQOh8-1lmHw-t5JPooDxufo9_GygzlQN9_wyOwJgGVp9bNpcUoDSEeoqJrL-bmVjQ84M6gyTDEEgGGPTYmjfc/s1600/Screen+Shot+2011-10-04+at+12.47.42+AM.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuzit3-41mx3eREU9kSuHvSZ9KVQkbYuUD8gCnfyDNt5-tTg76ytYVu6xQOh8-1lmHw-t5JPooDxufo9_GygzlQN9_wyOwJgGVp9bNpcUoDSEeoqJrL-bmVjQ84M6gyTDEEgGGPTYmjfc/s320/Screen+Shot+2011-10-04+at+12.47.42+AM.png&quot; width=&quot;192&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
If you are looking for a bit more complicated example there is one available in my GitHub repository:&lt;br /&gt;
&lt;a href=&quot;https://github.com/LambergaR/layout_demo&quot;&gt;https://github.com/LambergaR/layout_demo&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Yes, it has &#39;rainbows&#39; ... but hey, we&#39;re in &lt;a href=&quot;http://en.wikipedia.org/wiki/San_Francisco#Culture_and_contemporary_life&quot;&gt;San Francisco&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinsonc.blogspot.com/feeds/3641206057987013439/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/473673253554187747/3641206057987013439' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/3641206057987013439'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/473673253554187747/posts/default/3641206057987013439'/><link rel='alternate' type='text/html' href='http://martinsonc.blogspot.com/2011/10/final-touch.html' title='Fine Tuning Android Layouts'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11056772522189154527</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkKMpIskKjbLHipg-wuPEwnWVSc2AT_utwuSFuL7AS78bIU3hJHKX1GjIDs2-XYS54mWhdMNkBux83D0gkKCEyiez_dteAbBFfmpZFatJj-AS3PD2P8zmAbKgDNqDJVtk0gsKKfQMAFUE/s72-c/ss-320-0-4.jpeg" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>Palo Alto, CA, USA</georss:featurename><georss:point>37.4418834 -122.1430195</georss:point><georss:box>37.3410269 -122.30094799999999 37.5427399 -121.985091</georss:box></entry></feed>