Friday, October 28, 2011

Using Dropbox to share Ubuntu desktop state between multiple machines

I like to have my desktop shared between multiple Ubuntu machines so that I can just log in the another computer and continue to work on my "stuff". Shared desktop is also useful if you need to reinstall one of your Ubuntu box instantly (for example because of the broken version update) and do not want to lose the state of your desktop.

The trick is simply to remove your original desktop directory and to create the symbolic link to the directory in your Dropbox folder instead.
hekonsek@Drone:~$ rm -r ~/Desktop
hekonsek@Drone:~$ ln -s ~/Dropbox/Desktop ~/Desktop
Now all changes to your desktop state will be synchronized with the Dropbox account. Apply this configuration trick to all your machines and you got desktop synchronized between multiple Ubuntu instances. Plus desktop backup for free :) .

Wednesday, October 26, 2011

Passing Java arrays to Scala classes - generics compatibility issue

Imagine that you got a library class written in Scala (2.8.0). The class holds an array of Strings.
class LibraryClass(array : Array[String]) {

  override def toString = "Array size: " + array.length.toString

}
Now you want to instantiate this class from Scala code:
object ScalaClient extends Application {
  var libraryClass = new LibraryClass(Array[String]("foo"))
  println(libraryClass)
}
You can do the same from Java code:
public class JavaClient {

  public static void main(String[] args) {
    LibraryClass libraryClass = new LibraryClass(new String[]{"foo"});
      System.out.println(libraryClass);
  }

}
No problems. Everything compiles and runs smoothly.

Now modify the LibraryClass to be parametrized:
class LibraryClass[T](array : Array[T]) {

  override def toString = "Array size: " + array.length.toString

}
Try to run it from Scala code:
object ScalaClient extends Application {
  var libraryClass = new LibraryClass(Array[String]("foo"))
  println(libraryClass)
}
That works fine. Now try to call the parametrized version of LibraryClass from Java code:
public class JavaClient {

  public static void main(String[] args) {
    LibraryClass<String> libraryClass = new LibraryClass<String>(new String[]{"foo"});
      System.out.println(libraryClass);
}

}

Exception in thread "main" java.lang.NoSuchMethodError: LibraryClass.<init>([Ljava/lang/Object;)V
 at JavaClient.main(JavaClient.java:6)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:601)
 at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Yes, we've just created the code that is runnable under Scala but fails if called from Java. To make our LibraryClass compatible with both Scala and Java clients we need to narrow its parameter type definition to classes extending from the java.lang.Object:
class LibraryClass[T<:Object](array : Array[T]) {

  override def toString = "Array size: " + array.length.toString

}
Tip of a day - if you intend to use your Scala classes from Java code declarate their type parameters as [T<:Object] instead of [T].

Wednesday, October 19, 2011

Android resources summary

This is the summary of Android resources I find particularly useful.

Books
  • Hello, Android (3th edition) by Ed Burnette, Pragmatic bookshelf, 2010

Tools documentation

Friday, October 14, 2011

Starting up the Android project with android-maven plug-in


For some people (like me) all software projects must be Mavenized. Android projects are no exception from this rule.


The motivation behind using Maven with Android is:
  • dependency management 
  • smooth integration with Maven lifecycle
  • support for exisitng tools (Continious Integration, ProGuard obfuscator, Check Style, Find Bugs, JDepend, etc) via Maven plug-ins system
I decided to try out android-maven plug-in since it is recommended by the Sonatype.

At first I created the Android project from the archetype...

mvn archetype:generate \
  -DarchetypeArtifactId=android-quickstart \
  -DarchetypeGroupId=de.akquinet.android.archetypes \
  -DarchetypeVersion=1.0.6 \
  -DgroupId=helloCompany \
  -DartifactId=helloAndroid

...and then built it...

hekonsek@Drone:~$ cd tmp/helloAndroid
hekonsek@Drone:~/tmp/helloAndroid$ mvn clean install
...
[INFO] Installing /home/hekonsek/tmp/helloAndroid/target/helloAndroid-1.0-SNAPSHOT.apk to /home/hekonsek/.m2/repository/helloCompany/helloAndroid/1.0-SNAPSHOT/helloAndroid-1.0-SNAPSHOT.apk
[INFO] Installing /home/hekonsek/tmp/helloAndroid/target/helloAndroid-1.0-SNAPSHOT.jar to /home/hekonsek/.m2/repository/helloCompany/helloAndroid/1.0-SNAPSHOT/helloAndroid-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 13 seconds
[INFO] Finished at: Wed Oct 12 20:47:26 CEST 2011
[INFO] Final Memory: 42M/493M
[INFO] ------------------------------------------------------------------------

At first glance everything went fine so we expect to have Android APK artefact packaged and ready to be deployed to the device. However when I try to do the latter I get the following error message:

hekonsek@Drone:~/tmp/helloAndroid$ mvn clean install android:deploy 
...
[INFO] 279 KB/s (14872 bytes in 0.051s)
 pkg: /data/local/tmp/helloAndroid-1.0-SNAPSHOT.apk
Failure [INSTALL_FAILED_INVALID_APK]
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------

I also tried to deploy the APK file manually (using the ADB tool) but Android emulator still claims that the package is broken. I assume then that the current android-quickstart archetype is broken.

My workaround for the broken android artefact is to download zipped samples from the android-maven plug-in site and use Scala example as a template for my new project. As a bonus, Scala sample comes with tests, Scala language support and ProGuard obfuscator configured.

Now just start your Android emulator, go to the directory of the project of yours, build the project and deploy it to the running emulator.

hekonsek@Drone:~$ cd jayway-maven-android-plugin-samples/scala
hekonsek@Drone:~/jayway-maven-android-plugin-samples/scala$ mvn clean install android:deploy
...
[INFO] [android:deploy {execution: default-cli}]
...
[INFO] 170 KB/s (8959 bytes in 0.051s)
 pkg: /data/local/tmp/Scala-1.0.0-SNAPSHOT.apk
Success
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------

Now enjoy your new Android application deployed and running on the emulator.