Monday, November 14, 2011

Roboinstaller: Install roboguice dependencies in your device

Yesterday I wrote about a crazy idea of installing your application dependencies in the device to make the builds faster. This is just an example of what's possible.

After yesterday's idea I decided to give it a try and install in my rooted nexus one all the roboguice dependencies to see if my build times improved. To test it out I Manfred Moser's roboguice sample code called: roboguice-calculator.

Mike: I was going to test with the Astroboy roboguice's demo, but I didn't feel like dealing with hg. Plz move roboguice to git :)

To do this I have separated the whole process in steps.

Pre-dexing step

First of all, you need to get a pre-dexed jar files of all the dependencies. You can pre-dex your jar files with the following line:

dx -JXmx1024M -JXms1024M -JXss4M --no-optimize --debug --dex --output=./my_dep_dex.jar my_dep.jar

Creating the permissions XMLs
Once you get all your dependencies pre-dexed, you need to create the permissions XMLs which looks like this:

<permissions>
<library name="my.dependency"
file="/data/data/com.nasatrainedmonkeys.roboinstaller/files/my_dependency_dex.jar" />
</permissions>

Installing the dependencies
After some hacking to the scala-android-libs src code I had the code ready to install dependencies on the device.

Modifying the AndroidManifest
Inside the tag you need to add all your dependencies with the <uses-library> tag. It should look like this:

<uses-library name="my.dependency"/>

Modifying the pom.xml
The last step is setting the scope to provided using provided tag.

Results
Building the ordinary app: Total time: 22.212s

With this hack: Total time: 10.431s

Issues
Since mvn doesn't create a jar file with all the dependencies inside, I failed on my first try because the guice dependency needed the javax.inject jar file. I guess there should be a way to create a "fat-jar" with every dependency inside. If that's possible pre-dexing a dependency would be much more easier.

Future work
This has shown the approach is totally useful. Next step is to create an android app that can install pre-dexed files and create the xml without needing to recompile the whole application. This approach would also take me to separate my application into different libraries to develop as fast as possible :)

Source code
I have placed the installer code and the sample application with the modifications in this github repo: Roboinstaller

Installing dependencies on the device

This last two weeks I have been giving it a try to Scala on Android. While learning how to do it, I found something interesting I would like to share.

Developing Android apps using scala

The big problem of developing in Scala is that Android doesn't provide a way to install dependencies on the device. So, if you want to use Scala you need to place the scala's jar in your apk.

Placing the scala jar inside the apk bring another problem, apk size. To fix this, scala developers use proguard to remove all unused classes from the scala jar.

Using proguard to remove unused classes works like charm but it brings a third problem. Compilation time. For me, it takes a whole minute to compile an application with a single Activity coded in scala.

Conclusion:
Coding scala in Android is as frustrating as testing android apps :)

While looking for a solution for this, I asked a question in stackoverflow and it was answered by @jberkel. He pointed me to a project called scala-android-libs created by Johannes Rudolph.

What this project does is very interesting. It installs the scala's jars in a rooted device and allows the application to use it through the AndroidManifest tag uses-library.

How does it work?

It creates a serie of XMLs in /system/etc/permissions that look like this:

file="/data/data/net.virtualvoid.android.scalainstaller/files/scala_actors.jar" />

This means that if inside the AndroidManifest the app says:


It will be able to use the scala_actors.jar file inside the /data/data/net.virtualvoid.android.scalainstaller/files/ folder as a dependency.

Since now we have the jar installed in our device, we can avoid the proguard step and the build times are very similar to build an ordinary java app.

Taking it further
Every time I develop an android application I start creating a maven project because I know that I will use certain dependencies. After learning about this approach I thought about leaving my dependencies inside the device.

Why don't extending scala-android-libs approach to provide a way to manage dependencies inside the device to make the build times faster?
Perhaps having an android app that allows to install/remove jar files and automatically generate this XMLs with the proper permissions.

What do you think?
Would you use it?

Thursday, September 1, 2011

Playing with the new ViewPager class


Some days ago we released our latest work for on-mag.net, a magazine for mobile devices. The application already existed in ios so we did a port to Android.

Since we wanted portability we decided to create an hybrid application. An hybrid application is a mixture of native code and WebViews with HTML+JS+CSS. During the development of the application we found some android issues and some interesting implementation problems which I will describe in the following lines.

Btw the application is ready to download in this link.

APK size limitation
While in the ios world the ipa size limit is 2 GBs in the Android market is just 50MBs. After zipping our resources we ended up with a 200MB zip file.

To solve this we create a splash screen activity where the user get a dialog asking him if he wants to start the download. When the download starts, a Service is created and the download starts.


To avoid the download to halt we decided to add a partial wake lock with the following code:

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
wakeLock.acquire();

In the docs, it says:
Wake lock that ensures that the CPU is running. The screen might not be on.

Even thought the docs don't say if the wifi stays on, using a full wake lock didn't make a lot of sense. I tested on a nexus one and a nexus S and everything went fine, BUT yesterday I was talking to Christopher and he mentioned that his download stopped when the screen turned off. He tested on a Desire Z, running 2.3.3 (CyanogenMod 7.0.3). Let me quote his research:

There doesn't really seem to be a disconnection when the screen is off for a short time. Using "netstat" shows that the HTTP connection is still open; it's just not transferring anything. Usually when I turn the screen back on, the transfer will continue. Probably if it's idle for a long time, the connection is dropped.

I just tested this behaviour between WLAN and 3G. Network activity continues when the screen is turned off and the device is on a mobile network. If the device is on WLAN, the network activity pauses when the screen is turned off.

The Android Market shows the same behaviour on my device. It uses a partial wakelock for its DownloadManager but most network traffic pauses while the screen is off, if using WLAN. When the screen is turned on again soon, the traffic resumes.

Having to create a download Service from scratch was quite a pain. I know there is already a DownloadManager but it's only available in Android >2.3. It would be nice to have something similar to JakeWharton's ActionBarSherlock but with the DownloadManager.

ViewPager
If you never heard about the ViewPager go and read Rich Hyndman's blogpost.

I made a small demo with some stuff I found.
You can get the source code from this link and the apk from here.
I will explain what I am trying to show in each test.

Restarting
The magazine app was meant to be portrait only but it did have some landscape resources.
For example:

Portrait version


Landscape version


So, the Activity holding the ViewPager needed to be portrait only / portrait-landscape depending on the opened page. In the example every page index %2 == 0 has a landscape version. The test is called Restarting because every time we rotate the device, it will recreate the whole view.

WebViews
This tests shows how to deal with WebViews. Nothing strange.

WebViews Accelerated
I would say this is an android bug. If you place WebViews and you make your Activity hardware accelerated you will notice that the WebViews will start to invalidate themselves in a wrong way.

Unfortunately we couldn't find a solution for this and ended up leaving the app without hardware acceleration :(

Here's a screenshot of the issue:
WebViews accelerated

When moving through pages you will see some blue boxes for my blog since the background is blue.

VideoView
We tried really hard to make the HTML5 video tag work in android but we failed.
You can try this link .
The video used in the demo is from that site, I hope the author doesn't get mad about that :)

The first test doesn't say much, just shows VideoViews inside a ViewPager. All the pages are portrait only.

VideoView Resizable
This second VideoView test is more interesting. It tries to reproduce youtube's app behavior.
You can read about this issue in the following stackoverflow's question.

Instead of using the technique in the "Restarting" test we handle the change of orientation by hand changing the videoView's layout params.

VideoView Resizable with Margins
Similar to the last one but with the possibility of using margins. I just placed this test because when testing in the real app when the videoView got resized it didn't end up with the original size. I couldn't reproduce it :(

You will still notice that there is also a bug when you start changing from portrait to landscape. Here's an screenshot:
Media controller in the wrong place


Conclusion
Android 3.x has bugs and some of them will make you wonder how they could make the slip. On the other hand the introduction of the compatibility library brought an excellent weapon to fight fragmentation. For instance, the demo's min sdk is 4. I can be sure that I am leaving just a small group of users out.

PS: Talking about android 3.x bugs/issues. If you try running the demo with target sdk 13 and compile against 3.2 onConfigurationChanged() will never get called. The WTF per second is increasing drastically :)

Thursday, August 25, 2011

Error retrieving parent for item

Some days ago I updated the android platform-tools to r6. Everything went fine and it really called my attention :)

Yesterday I tried to open a one month old honeycomb application and I got errors in my styles.xml file.

Eclipse said:

error: Error retrieving parent for item: No resource found that matches the given name 'android:style/Widget.Holo.Light.ActionBarView_TabView'.

After:
  • Trying to build with eclipse
  • Trying to build with mvn from the cmd line
  • Removing my .m2 repo
  • Replacing my android jar with another
  • Comparing the mvn -X output with someone's who had it working
I discovered issue 18659: aapt cannot resolve parent reference to @android:style/WindowTitle

Formal explanation:

What is happening is that some styles, like WindowTitle are not public (you won't find them in android.R.style). You should not be extending non public resources. aapt used to let you do that but it was a bug which was fixed in platform-tools r6.

Ok, great I can't extend non public resources, but my style code was copy and pasted from @crafty's blog post: Customizing the Action Bar!

After testing his code I noticed that it also didn't work. Note: There is an issue created for this.

Just for the record, here's how to fix it.
What we need to do is avoid extending the non public resources and copying all the items in our own style.

The two styles that generate the error are:

<style name="MyActionBarTabStyle" parent="android:style/Widget.Holo.Light.ActionBarView_TabView">
<item name="android:background">@drawable/actionbar_tab_bg</item>
<item name="android:paddingLeft">32dp</item>
<item name="android:paddingRight">32dp</item>
</style>

<style name="MyDropDownNav" parent="android:style/Widget.Holo.Light.Spinner.DropDown.ActionBar">
<item name="android:background">@drawable/ad_spinner_background_holo_light</item>
<item name="android:popupBackground">@drawable/ad_menu_dropdown_panel_holo_light</item>
<item name="android:dropDownSelector">@drawable/ad_selectable_background</item>
</style>


Let's fix MyActionBarTabStyle.
To fix it, we will need to copy every non modified items to our style.
We need to open styles.xml at $ANDROID_SDK/platforms/android-11/data/res/values

There we see:

<style name="Widget.Holo.Light.ActionBarView_TabView" parent="Widget.Holo.ActionBarView_TabView">
</style>

No items there, let's now search for: Widget.Holo.ActionBarView_TabView.

<style name="Widget.Holo.ActionBarView_TabView" parent="Widget.ActionBarView_TabView">
<item name="android:background">@drawable/tab_indicator_holo</item>
<item name="android:paddingLeft">16dip</item>
<item name="android:paddingRight">16dip</item>
</style>

There we find three items and we still need to continue up with Widget.ActionBarView_TabView:

<style name="Widget.ActionBarView_TabView">
<item name="android:background">@drawable/minitab_lt</item>
<item name="android:paddingLeft">4dip</item>
<item name="android:paddingRight">4dip</item>
</style>


Great. The same three items and we already have it in our own style. We can get rid of the extension. Leaving our style like this:

<style name="MyActionBarTabStyle">
<item name="android:background">@drawable/actionbar_tab_bg</item>
<item name="android:paddingLeft">32dp</item>
<item name="android:paddingRight">32dp</item>
</style>

The fixed MyDropDownNav ends up extending something non public. It should look like this:

<style name="MyDropDownNav" parent="android:style/Widget.Holo.Light.Spinner">
<item name="android:background">@drawable/ad_spinner_background_holo_light</item>
<item name="android:popupBackground">@drawable/ad_menu_dropdown_panel_holo_light</item>
<item name="android:dropDownSelector">@drawable/ad_selectable_background</item>
</style>


I honestly don't understand what makes an style private or not. They only way I found is checking android.R.style class. If someone knows a better way, please let me know!

Conclusion
Android development has this type of tricks. Fortunately the active community report issues and write about workarounds so everyone can avoid some of the pain :)

Happy coding!

Tuesday, July 12, 2011

cursor.getString() vs cursor.copyStringToBuffer()

Some days ago cyrilmottier posted a blog post about ListView's tip and tricks.
In one of his tips he mentions the following:
CharArrayBuffer: Developers are regularly using the getString() method on the Cursor. Unfortunately, it implies creating String objects. These objects are likely to be garbaged once the user starts scrolling. In order to prevent object creation and consequently garbage collection freezes, it is possible to use a CharArrayBuffer that consists on copying data from the Cursor to a raw array of char that will be directly used by our TextViews. Instead of having to create aString object, we will hence reuse a CharArrayBuffer.
My first thought was: Oh my! I am using getString() everywhere! We had some performance issues in the past with a Gallery so it was a great place to start fixing the code.
Yesterday evening I modified the adapter's code to use CharArrayBuffer instead of getString(). When I tested the app it felt slower than before and very blocky. I went to sleep.


Traceview:

Today evening I decided starting from the scratch, but instead of using my app I decided to create a toy app. I stole some code from @vogella and start testing.

You can download the app from this link.
My first test was with the traceview tool:



In the screenshot you see two instances of the traceview tool analyzing the bindView method.
Over the top, you can see
withoutFix.trace (the one using the cursor.getString() method) and below the withFix.trace (which is using the cursor.copyStringToBuffer).

Another thing I took some time trying to understand is this:


Conclusions so far:
* Using cursor.copyStringToBuffer() seems to run the bindView method faster than cursor.getString().
* cursor.getString() is faster than cursor.copyStringToBuffer()

The difference is not much so I wouldn't take care of keeping the fix. The code looks clearer with the getString() method.


MAT:
But wait, let's give it a try to the Memory Analyzer (MAT).
Note: After hearing @dubroy's talk at the googleIO 2011 I wanted to do something like this :)

@dubroy also wrote an article for the Android Developers blog called "Memory Analysis for Android".

What I did was comparing two heaps from both options.




Objects #0 and Shallow Heap #0 are for the cursor.getString() version and
Objects #1 and Shallow Heap #1 are for the cursor.copyStringToBuffer().

Not much to say here.
* The getString() versions has less String objects.
* The copyStringToBuffer uses more heap. (I use three new CharArrayBuffer(128))


Final conclusion:

I am not an expert using this tools but, from what I have tested, I couldn't notice a performance improvement when using cursor.copyStringToBuffer().

What do you guys think?

UPDATE:

I had the following conversation with cyrilmottier over twitter:
cyrilmottier: The actual benefit is you will reduce garbage collection to a minimum. This is less useful in Android 2.3 or higher.

2.3 introduced a generational GC. Hence, CharArrayBuffer is probably more useful on old Android versions.

me: It makes sense. I will keep the getString() calls, knowing that I have the buffer if I need to improve memory usage.

Sunday, July 10, 2011

Android market: Books y Movies en Argentina?

Ayer estuve browseando el android market desde la xoom y se me dio por entrar a Books y Movies. Por suerte ya no son secciones vacías. Veamos qué se puede hacer!

Books
Por ahora se puede browsear los libros,


pero cuando querés entrar en el detalle de alguno muestra un error:


Movies
A diferencia de los libros, las películas muestran otra información.
La pantalla principal se ve así:


El filtrado de las películas todavía no existe. No puedo buscar por año, ni por precio.
En Comedias encontré una que no había visto. Matchstick Men. La pantalla del detalle fue la siguiente:


El problema ocurrió cuando la quise comprar. Lamentablemente no aceptó mi tarjeta de crédito:



GoogleTV
Todavía no hay novedades de honeycomb para googleTV. Aparecieron dos updates pero ninguna interesante.
La versión de googleTV que tengo ahora no permite acceder al market pero hay dos opciones que permiten acceder a Netflix y a Amazon Video.

  • Netflix no entra diciendo que todavía no está en Argentina.
  • Amazon Video te permite browsear pero cuando querés comprar te dice que necesitás tarjeta de crédito de EE.UU. y domicilio de allá.

Conclusión
Existe un pequeño avance desde la última vez que probé, pero, por ahora, seguimos lejos de poder alquilar una película por internet. Netflix ya anunció que va a abrir en Argentina, así que a esperar un poco más :)


Thursday, May 26, 2011

Connecting usb stuff to the Xoom and debug through wifi!


Today I played a lot with my Motorola Xoom trying to connect different devices.

Games
We started connecting the tablet to the television using the hdmi output. We installed Snes9x EX and played some snes games. The great thing about Snes9x is that it allows to connect Wiimotes. The screen over the right shows a Killer Instinct fight!

Kinect
Today at work they bought a Kinect to test stuff. Android 3.1 + usb host == kinect? I entered the freenode irc chat of the openkinect guys. They give me some excellent support but they doubted that it would work. I will try it out. If I found something useful I will do a blogpost about it.

USB keyboard/mouse
The usb keyboard worked fine but the mouse didn't. The mouse turns on, but the pointer doesn't appear in the screen.

Other Android devices
One of the samples of android-12 is called AdbTest. You can connect an android device and it will read the logs. I connect my nexus one and it worked fine.

Hacking
Cool. Good results so far but I felt disappointed with the mouse, so I decided to try to read what the usb say for that device. When I was going to connect the mouse I discovered that I was missing an extra slot for debugging. I first based my code in the AdbTest and place my logs in the TextView.

After failing trying to get the device name I started reading the documentation, and I found there were Debugging considerations when using the USB Host and Accessory. There are five easy steps you need to do to debug without a usb cable.
  1. Connect the Android-powered device via USB to your computer.
  2. From your SDK platform-tools/ directory, enter adb tcpip 5555 at the command prompt.
  3. Enter adb connect device_ip:5555 You should now be connected to the Android-powered device and can issue the usual adb commands like adb logcat.
  4. To set your device to listen on USB, enter adb usb.
It does work!

I needed to post this before continue coding :)

Friday, May 20, 2011

App Review: ESPN 107,9. A real Honeycomb app?

On Thursday I went to the Motorola's MOTODEV. You can find a review of the event here. Thanks @fogo!

One of the sessions was called: "Moving Your Smartphone App to the Tablet". There they showed an app done in Argentina which was ported to tablets. My first thought was: "Cool, someone already ported something here in Argentina". Today I installed it and I found very interesting stuff in this app so I decided to create a review.

Installation and market place
I search for the app in the market and I found this:

This is what happens when you use two different binaries for the same app. Some of the issues are:
  • Different comments for the same app.
  • Different ratings for the same app.
  • Doing an update means uploading two different apps.
Is there a real difference between those binaries? We will see.

Patterns and features explained
In this section I will explain some of the patterns that the app uses. Also some features/issues and a way to solve them.

Splash Screen
This is something used a lot in iPhone's app. While an app loads in iPhone the os shows the image /Default.png or /Default@2x.png. It does make sense to use a splash screen if you need to load something before loading the application itself. One of the best examples is Roboguice's RoboSplashActivity:

An activity that can be used to display a splash page while initializing the guice injector in the background.
To use this kind of patterns the attribute android:noHistory is your friend. In the case of the app it looks like they didn't use it since there is a nasty bug that ends in a FC. If you enter the app and click "Programación" you can actually move back three steps when only two should be possible.

AndroidManifest
If you check their manifest you will notice that they are doing something like:

<activity android:label="@string/app_name" android:name=".ESPN_107_9" android:screenOrientation="portrait">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

intent-filter>

activity>

<activity android:name=".EspnHome" android:screenOrientation="portrait" />

<activity android:name=".EspnProgramacion" android:screenOrientation="portrait" />

<activity android:name=".EventoActivity" android:screenOrientation="portrait" />

<activity android:name=".Prueba" android:screenOrientation="portrait" />

<activity android:name="iphoideas.ESPN_107_9_TABLET.Example" android:screenOrientation="portrait" />


Some issues about this manifest:
  • It doesn't follow the java package name convention.
  • There is an android:screenOrientation="portrait" in every Activity when it can be placed just in the Application tag.
There is also an interesting use of android:name. In the manifest you can place a dot and that will be replaced by the package info placed in the manifest tag. As you can see, they have used both ways. The complete package name and the dot version.

Forced Portrait
This is what pissed me off as a user. No landscape view in the tablet version? Seriously?
The app has basically two Activities. The main one with a play button and some social features.


Social features
You can just send an email or paste something in your facebook's wall. Android has a lovely share intent to handle this stuff. You can get more information here.

System notification when playing
I started playing the radio and no system notification was shown. Not the same use case as the default music player?

Fragments
No fragments? Honeycomb application without fragments? I don't like to have a big play button in the main window and need to move to something else just to see the radio guide.

Creating a landscape layout having the radio controls in the same activity as the guide would have been great.

Stacked activities
In this app from the Home you can go to the radio guide and from the radio guide you can go to the home screen. So, you basically can do Home => Radio Guide => Home => Radio Guide. What happens if you press the back button? In this particular app all the activities get stacked but for this kind of situations android provides a solution. Using FLAG_ACTIVITY_CLEAR_TOP

For example, consider a task consisting of the activities: A, B, C, D. If D calls startActivity() with an Intent that resolves to the component of activity B, then C and D will be finished and B receive the given Intent, resulting in the stack now being: A, B.

Enable Hardware acceleration
Unfortunately this app doesn't use it. To do it you just need to add the android:hardwareAccelerated="true" in the application element.

Using the Holographic theme
This app doesn't use the holographic theme. Everything in this app is custom so you might thing that it's not necessary but when dialog show up they aren't custom and they don't use honeycomb styles.

If you are targeting smartphone and tablet you can use:
<uses-sdk minsdkversion="4" targetsdkversion="11"></uses-sdk>

Different resources for different screen sizes and densities
This app has every resource inside the res/drawable folder. Using the res folder correctly would be enough for this app to live in the same binary. There is a nice explanation about this here.

Conclusion
The conclusion is dead simple. This is not a honeycomb app. It works in honeycomb because it has: <uses-sdk android:minSdkVersion="7" />. It isn't targeted for Honeycomb and it doesn't use android 3.0 features.

Does anyone know if someone in Argentina already did a good honeycomb app?

Tuesday, May 17, 2011

Google IO 2011: Day two

Second day
If you didn't read the view of the day day, you should read that one first.

Breakfast

After eating something we met with Jason Van Anden. Jason worked with me while I worked in Teracode but unfortunately I never met him in person. He has an interesting project called BubbleBeats.

He told us about his plans and his future projects. It feels good to know that Android developers are getting tons of work and they are progressing!


Keynote


While the first keynote was all about android, the second day's keynote was all about chrome os and chrome browser.

Good news about ChromeOS. I think that everything sum ups to this sentence: "No need to bother fixing PC and having more time for yourself". I am particularly happy for that. I am tired of fixing PC with an OS I don't use anymore. As the times passes, it gets harder and harder to find the Control Panel :(


Google decided to give out chromebooks as a present but they are sending them on June 15th. I don't know how that will work for international attendees. I guess I will need to ask Al Sutton (@alsutton) :)


Building Agressively Compatible Android Games

This talk was given by Chris Pruett(@c_pruett). He was a Game Developer Advocate for Android at Google and now he has his own company. He once again talked about his experience with Replica Island and give out a big list of things to do and not to do.

I wish I could talk to him but he was surrounded by other people.

Lunch

After Chris' talk we hang around some stands which were in the third floor. There were a lot of games to try out and also some robots going around. After some of them we decided to head for Lunch. 20 mins to eat before moving to the next session. I need to say that the food was excellent. We even had a Haagen Dazs' ice-cream as dessert!

Building Web Apps for Google TV

Chris Wilson (@cwilso), GTV developer advocate gave an excellent explanation about the TV platform in general. He mentioned that we should get everything away from the boarders since the Over-scan also applies to nowadays televisions.

He also mentioned a lot of recommendations for UI design. Some of the ones that stayed in my head were:
  • Remember the user is in couch-mode. Few interaction.
  • Avoid having a lot of clicks to reach content.
  • Design your app and see it from 10 feet (3 meters) away.
  • Instead of browsing downwards, the user browses rightwards.
  • Avoid scrolling. The user is not used to scroll TV content.
  • Make sure you make the user aware of where he is standing and what options are available.

Building Android Apps for Google TV

Similar to last session, these guys gave an intro to Google TV.

They explained that the API will provide different functionalities/issues. There are two which are pretty interesting or out of the ordinary.

1) You will not be able to know what the user is watching.

Wow! Really?

Actually you can learn which channel he/she is watching but no more than than. If your app/idea depends on that you will need to ask the user which tv provider he/she is using and parse it's tv guide. While it's a big issue right now, I guess some kind of open source project will appear to solve this.

2) Android fw will start to take care of where to place your ui widgets. eg: If you place an ActionBar in your app in a Tablet device it will show in the top right corner horizontally while for GTV it will show in the left vertically. I guess this is what android ice-cream sandwich will be about. Developer placing a ui widget and android deciding how to show it correctly. Third party UI libs will need to take care of that kind of customization if they are willing to stay alive.

I actually asked Roman Nurik what he thought of different third party UI libraries. My question actually was: "Should we continue using libs like GreenDroid or we should wait for this kind of magic customizations by Android?". He replied that for now we are good to use that kind of libs. They are an excellent way of applying android ui patterns.

GTV Office Hours
After the Android GTV talk, we went to the office hours. I wanted to buy a google tv to take back home but I wanted to be sure that I was going to get the 3.1 update with the adb and stuff. We fortunately found Chris Wilson who friendly replied to all our questions. I will try to reproduce:

We: Logitech or Sony?
Chris: It depends. The sony has a bluray but the Logitech is cheaper. If it's just for development I will take the Logitech one.
We: Which one do you use at work?
Chris: Both.
We: Who's in charge of the updates?
Chris: The updates are sent by Logitech and Sony themselves.
We: If we get a gtv and start using in our country, we will get it?
Chris: Yep, you will get it while the device is connected to internet.
We: Is it possible to root the device?
Chris: Official answer: no. On the other hand, there are people who did it. It involves welding.

GTV Conclusion
In general, GTV it's a US-only device for now. I got one for several reasons.

  1. Being able test gtv apps for clients from US.
  2. We want to explore the world of widgets for GTV.
  3. Porting cocos2d-x to GTV. I still need to make it work with Honeycomb but I will definitely want cocos2d-x to run in GTV :)

Bringing C and C++ Games to Android

Since we had some time we decided to go to this session to meet up with @emmby. We reached there for the Q/A. When we entered a guy was leaving and the speaker said: "Try staying, there is a present for everyone in this room". Yep, I also got a xperia play. I guess I will need to discuss with the cocos2d-x's guys how they are willing to support this kind of device.

How to NFC
I didn't attend this session, but @mpan_ did. He said that they spoke about the api in general but for now android devices with NFC will not be able to emulate a NFC card.

After party
After the conference we went out for some drinks with ppl known by @emmby. Going out with ppl that knew SF was excellent. We went to different bars and we ate in an Indian restaurant. It was actually the most spicy meal I ever had, but I enjoyed it a lot. Thanks guys!



Conclusion

The Google IO was excellent. Good amount of sessions, every technology showed it's work in progress and I got an excessive amount of gifts.


Every android release is very ambitious and the next one is going to to support cellphones, tablets and tv. I think that GTV will be the next big thing. I yet don't imagine my dad using an android powered device but I do imagine him using gtv. From my point of view gtv will bring new type of users to the android community.

We also need to pay attention to tablet apps. There are very few apps in the market. The user experience of a tablet user is very frustrating. I hope to see more tablet compatible apps. I guess I should start doing that with my own apps.

There are a lot's of ideas and stuff to do in my head. I will now need to find the time to do them all.

Cheers, and happy coding :D

Wednesday, May 11, 2011

Google IO 2011: Day one

Google IO 2011: Day one

Ok, here's my little review of the #io2011. I will try to focus in the technical stuff only.


Keynote
Amazing stuff. It really feels like Android is taking to the next level.


There were a bunch of announcements with tons of stats but for developers, the important stuff was:

  • Android Honeycomb 3.1 will be rolling out for the Motorola Xoom.
  • ADK
Android honeycomb 3.1 will be available not only for tablets, but for Google TV as well. This means that if you target 3.1 you will be targeting Tablets + TV. Here are the platform highlights.

There is this new resizable feature and it feels like a widget is a must for a tablet app. And what about using widgets in googleTV? It looks like Android's widgets will turn into something important. I never did one so I guess that's something I will need to research about it.

ADK
Honestly I was expecting something like the ADK toolkit. This new idea of android accessories open a new world of ideas. I feel that in a couple of months I will start plugging in my cell phone on every appliance at home. I am not very good with electronics but I know someone that will be interesting in doing something with it :)

Talks and office hours
With Matias we decided to avoid most of the presentations for two reasons:
  • They were very crowded
  • We preferred to talk to the Android developers and ppl in general.
We did enjoy a lot of talks so I will try to sum up what we talk about.

Romain Guy (@romainguy)
Some weeks ago, I had a very hard time making ListView work with choices modes. Fortunately I got a nice answer by Mark Murphy. Just to give you an idea, choice modes just work fine if the view returned by the adapter implements the Clickable interface. This means that you need to create a custom view.

I speak to Romain about this and I suggested to throw an exception when the ListView uses a choice mode but the view doesn't implement Clickable. He basically said that the ListView might have different views, eg sections, so it would make sense.

There is not much to do but to understand how ListView works and use it correctly. I suppose I will share some code of this working and how to use it since the ViewHolder pattern is used differently.

Virgil Dobjanschi (@vdobjanschi)
Virgil is the speaker of one of the best io2010 talks. Maximiliano Gomez Vidal (@mgv) gives a nice explanation of Virgil's talk in his blog post: The revenge of the SyncAdapter: Synchronizing data in Android.

The last month we started working in a new honeycomb app and we decided to follow Virgil's advises. I can't share the code but here are some highlights of our approach:

  • One ContentProvider per REST call.
  • One SyncAdapter per REST call.
We reached to some issues with this approach. We had something like:
  • REST call for getting SMS threads.
  • REST call for getting SMS from a certain thread.
I guess you can notice the issue here. SyncAdapters can not have dependencies, or be called in a certain orden so our approach breaks with this. We also didn't want to merge both REST calls in a single SyncAdapter since we didn't want to waste user's bandwidth downloading SMS which were not needed (Typical example of threads in the left and message showing up after clicking in a thread).

So, after explaining everything to Virgil he mentioned that in the past he was doing something similar to us. Different sync adapter per model but he said that after discussing with other android developers he was doing:

  • Only one sync adapter per app.
  • One Content provider per db.
My immediate question was: So you are having long classes with big switch statements? His answer was yes.

I also asked how he was handling manual updates for different models and he answered that he was using intents. I assume that there is a cute switch statement as well :)


Lunch

The place where we had lunch was huge. We had the chance to share the table with Felipe "java." Lang (@flang). He is part of the GTUG from Santa Fe, Argentina. The @santafegtug.


ADK



We ended up going to this talk. The talk was low level stuff but the speakers left a lot of time for questions. One of the best questions was: "If I do an android accessory does it need to get certified? What are the legal terms with all this?" The answer was: "Good question, issue a bug!"

The lack of legal terms was actually one of my concerns during the Google IO.
Music service, cool. Can I upload my music? Is it legal?
Movie rentals, cool. I can cache my movie to watch offline. Is it legal?
Google TV, cool. Is getting banned from some tv providers. Is it legal?

It feels like the technology is there but we are lacking some legal terms and information of what's possible and what's not.

All the ppl in the room got a ADK kit.
In the ADK talk I met Michael Burton (@emmby). He's the author of Roboguice, author of the Groupon's app and a very nice guy.

Firechat
Nothing very important in this talk but just an excellent panel.
Unfortunately the questions weren't very interesting.

Android office hours
We team up with @emmby and we stayed in the android office hours room. There we had a change to discuss ideas with different people.

Roman Nurik (@romannurik)
Roman was very friendly. I had an issue with how fragments handled touches so I asked him about it. He mentioned that fragments had nothing to do with the View hierarchy. I will have to recheck my code and try to answer my own question.

With @emmby we were both concerned about issues in the android issue list. We asked @romannurik if someone was actually reading them :). He said yes but that they were full of work.

Diana Hackbood
I had the chance of talking to Diana. I founded an issue with the LatinIME while working for SwiftKey. She told me if I knew how to fix it, I could provide a patch in gerrit.


Virgil Dobjanschi + Michael Burton
After speaking with Diana I found that michael was speaking with Virgil. I jump into that conversation since I knew it was going to have a lot of juice.

Michael was saying that he was using AsyncTask instead of going through all the syncAdapter + ContentProvider thing.

Virgil mentioned that doing the content provider and designing the db was the first thing he did but Michael said that you could only do that when the APIs didn't change which wasn't his case.

We three agreed that the documentation for SyncAdapters was lacking and even when you understand it correctly, it was a lot of work. I take advantage of the discussion and asked Virgil if he tested some kind of framework like DB4O for his approach. He said that we wasn't willing to replace Sqlite since he could add performance tweaks easily. I guess it's something we should test out with @mgv and blog about :)

Rallat (@rallat)

At the end of the day we met Rallat. Rallat is a GTLUG member from Spain. He is also in charge of and.roid.es, a spanish android site.

Unfortunately he told me that he was changing the dates of the Spain's Droidcon.


After party

The after party was incredible. Lot's of good food and drinks. Nice music and even a bugdroid dancing techno music.


Pretty Good for a first day!


Update: Review of the second day.


PS: Blogger needs an offline chrome app. I am in the plane right now and I am not able to save my writing :(

PS2: My flight is leaving!


Sunday, April 24, 2011

Making your Android app look pro

The idea of this blog post came from this stackoverflow question. Since I just updated my app using most of them, I wrote how and why did I change stuff. Here we go...

Intro
One year ago or so I was releasing my first android app to the market. A Traffic status application for my home city, Buenos Aires, Argentina.

Just to place you in the correct time frame, the Google IO 2010 was just finished, the twitter app was release and a lot of new android UI patterns were out. Unfortunately there were no third parties to apply this UI patterns so I basically did what I could.

I recently updated this application and instead of using my approach I migrated most of my code to third parties. I will try to show how it look in the past and how it looks today.

You can get it from the Android Market or clone the public repo at github.

Home screen
The home screen is was the user sees the first time. It's usually a combination of an ActionBar and a DashBoard with all the possible actions for the user. We can compare the old and the new one in figures 1 and 2.


Figure 1: Old Home screen.


Figure 2: New Home screen.

Quite different, huh?
Let's see how I changed that.


Action Bar
This UI pattern was introduced by The GoogleIO and the Twitter app.
As usual, no source code, no library.

In estadoDelTransito it was implemented as a custom title bar. It was an ugly hack. After the google IO app source code was released, I noticed that the correct way to do it was removing the title bar and adding a widget in your layout which would work as a title bar.

Now adding an ActionBar to your application is very easy thanks to Cyril Mottier, author of GreenDroid. You can download GDCatalog and see how it's used.

Dashboard
The dashboard pattern is about showing the user what the app can do.
Lot's of apps use this: GoogleIO, Twitter, Facebook, Hubdroid.

In the past, I just did a RelativeLayout and I placed different items in the screen.

Nowadays you just need to place an extension of ViewGroup created by Roman Nurik. You just need to place this DashboardLayout as your parent view and place some Buttons with the android:drawableTop property.

You can notice that my version centers the items while Roman's use the whole screen. Roman's version also fixed how it was viewed in ldpi displays.


Long press vs Quick Actions

The long press actions and the menu options was something I hated in Android. It was hard for the user to notice there was more functionality behind a long press or contextual menus when hitting menu. Fortunately, they are disappearing. For instance, in Android Honeycomb I don't remember seeing any of them.

Where I used them in estadoDelTransito?

a) All activities have a menu option to go back to the Home Screen. The explanation for that functionality is simple. If you travel throughout the app going back to the home screen would require a lot of back button press.

The menu option was replaced by an ActionBar button. Every screen has a HOME button on the upper left.

b) Long press in ListView's items get a contextual menu providing additional actions for that particular item. Most of the people that used the app didn't notice the existence of the long press functionality. They clicked on an item but nothing happened. You can argue that they were not android users but even myself missed some app's functionality just because I didn't try a long press in certain items. You can see how the long press menu looked like in Figure 3.


Figure 3: Long press menu in the old version


QuickActions to the rescue
GreenDroid also provides quick actions.
I don't like the fact that you need to extend GDActivity to provide quick actions. In the case of estadoDelTransito it works fine because I am using the ActionBar but now I am working in an android 3.0 app and I don't want to extend GDActivity. What if I want quickActions in a Fragment?

If you just need quick actions I would recommend you to use this.


ProgressDialogs
I didn't notice an issue with this until I listen to a talk by Reto Meier. He basically mentioned that, why would you use a ProgressDialog? Freezing the UI thread and placing a ProgressDialog feels the same, get rid of them.

In estadoDelTransito when you enter a screen, a ProgressDialog screen will show up until the info is updated. What's even worst, by default the ProgressDialogs are not cancelable, so if the user's internet connection was slow, he was stuck there. You can see how they looked in figure 4.

Solution? Use the ActionBar. Make the refresh widget spin there while the data is being loaded. If the user wants to go back, he can.

Figure 4: ProgressDialogs in action.

Map overlays
Adding map overlays for this kind of app it's a must but showing custom views when the user clicks on the map is not as simple as I would like it to be. In Figure 5 you can see how I did it in the past.

In the new version I am using a cool third party lib by Jeff Gilfelt called android-mapviewballons. I guess you can imagine what's for :)


Figure 5: Old popup for GMaps.


Conclusions
With the creation of Android libraries a lot of third party libraries came out. You just need to visit github, search for android and get an android library for what you are willing to do.

Nowadays, making your app look good is just a matter of seconds. There are no excuses :)