Showing posts with label maven. Show all posts
Showing posts with label maven. Show all posts

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?

Wednesday, November 17, 2010

TDD skeleton for Android

During this days at work my task was to research about adding tests to an Android application. The truth is that right now we aren't doing tests at all. In this entry I will try to comment on every framework I have been looking into. Let's start!

My first step was getting one of our applications and try adding black box tests. My first stop is robotium.

Robotium is a test framework created to make it easy to write powerful and robust automatic black-box test cases for Android applications. With the support of Robotium, test case developers can write function, system and acceptance test scenarios, spanning multiple Android activities.

Robotium has full support for Activities, Dialogs, Toasts, Menus and Context Menus.


Robotium is founded by the same company that created the maven-android-plugin that we have been using for a long time.

This framework looks great for blackbox testing but I didn't go too deep with it. I just made a test to browse around the app and check that the app shows the screen correctly. I had an issue with a SplashScreen but the feedback was great. I am really pleased with that.

When I reached this point my thought was: "Ok, now I can add blackbox test, but I also need unit tests!"
I try adding simple unit tests to the app but I failed. Classes were too dependent and there was lot's of logic inside the Activities. So I leave the real project away for a while and create a new one to start from the scratch with a new Architecture approach.

I present my last application: ioc_app. The ultimate app to turn a String to uppercase.


Link to the source code.

This project has two modules
a) ioc_app. The android application.
b) ioc_test. The test application.

Let me introduce some of the new stuff I added to this project:

1) Presenter first
I implemented this pattern based on the paper hosted in the link above. It's quite clear.

2) Proguard
When packaging an apk, all classes of all libraries used by the program will be included, this makes the apk very huge, even exceeds the capacity of dex. ProGuard can strip unused classes and methods, make it as small as possible.


I am missing adding proguard in an specific profile. It takes some time to compile and I don't want it to run unless I am building a release. Manfred, a committer in the maven-android-plugin project, told me he already did that and he uploaded to a sample project. I need to see that.

Manfred also mentioned he was trying to add obfuscation but he couldn't do it yet. Right now it's not my first priority but it's a nice to have feature.

3) Roboguice
Just to put it in a sentence: It's Google Guice for Android. I love the fact that from now on instead of writing:

mButton = (Button) findViewById(R.id.submit);


I will write:

@InjectView(R.id.submit)
private Button mButton;


Unfortunately Guice doesn't provide a mvn repo, so to use roboguice you will need to install guice-2.0-no_aop.jar in your maven repo.

4) Android-mock
I have some issues with this one. Running tests with mocks in Eclipse i'ts a PITA. Once again I got an excellent feedback but I preferred to go for the mvn approach.

Android-mock needs two jars to work. One for compile time and another for runtime. Right now it just work from mvn. I couldn't make it work from eclipse even though I have the m2eclipse-android-integration.

What's next?
* I am willing to read more about TDD. I have now everything configured to start doing it.
* I need to setup a Hudson to take care of the CI.
* I would like to start using IntelliJ IDEA but I couldn't manage to make my project run with it. If you did it, please let me know.

I'm hoping you give me some feedback about the skeleton and how to improve it!

Other blogs with useful info:
- http://dtmilano.blogspot.com/2008/03/test-driven-development-and-gui-testing.html
- http://www.rosscode.com/blog/index.php
- http://simpleprogrammer.com/