Pages

Tuesday, July 26, 2011

Dropbox and Git bare repository

Here's a nice tip for those who want to make development with Git but don't have a place to put their shared repository. You could use Github, but remember that any sources you put in the free version of Github are open for all users. So if you don't want to share your sources with everyone you could use e.g. Dropbox to share your code with your fellow developer(s) or just to backup your sources.

Create a bare repository
Create the directory which you want to share:
mkdir mydev.git
cd mydev.git

Initialize the repository and modify the Git config to enable shared mode (not needed for Dropbox but good to have if you move your bare repository to a proper server).

git init --bare

add sharedrepository=true to the config file.

Now you have a proper bare repository.

Share the repository in Dropbox
Copy the folder you initialized in your Dropbox folder. If you like, you can share it with your fellow developer(s).

Connect to your "Central Repository" and share your work
You can connect to your bare repository by executing the following command:
git clone PATH_TO_DROPBOX_FOLDER/mydev.git
cd mydev

Create some work to share
touch my_example_file.txt
git add my_example_file.txt
git commit -m "my first commit"

Git commit commits your work to the local repository but doesn't commit it to the central repository, so to share your work you need to push your work to the central repository.

git push

To get the work from the central repository, you need to do a pull operation:

git pull

Last I should warn you that we've had some issues with corrupting the central repository. We got everything working again by doing a new commit and push by the person who last changed the repository. However, despite the occasional corruptions in the central repository, there are several advantages to using Dropbox as the central repository, and it will make the development work a lot easier.

Monday, July 25, 2011

Adding Scala libraries to the Android emulator

After a couple of weeks' development we recognized that the compilation took vast amounts of time to complete and it really slowed us down. We tried using Android plugin's lazyunpack with rather poor results, as well as tweaking the Proguard, but clean compilation still took us almost 2 minutes.

After a short search we stumbled on a really interesting article about preloading the Scala libraries to the Android emulator. All we needed to do was predex our Scala library and create a custom ramdisk with some extra rules in the init.rc file for loading the Scala libraries during the emulator startup. Jan Berkel also had a really good tutorial about how to preinstall the Scala libaries to the emulator (and also to a rooted phone). With these resources at hand I first cloned the scripts provided by
Berkel from the Github (derived from Stéphane Micheloud's scripts).

git clone git://github.com/jberkel/android-sdk-scala.git
cd android-sdk-scala\bin
createdexlibs.bat

I needed to set SCALA_HOME and ANDROID_SDK_ROOT, to get the scripts to run correctly.
set SCALA_HOME=PATH_TO_SCALA
set ANDROID_SDK_ROOT=PATH_TO_ANDROID_SDK

I also had to manually modify the createdexlib.bat, since Google had changed the location of the dx compiler.

Then I configured the Scala 2.9.0 version into my SCALA_HOME variable and ran the scipts. I also downloaded the custom ramdisk.img (avd.v10 [2.3.3]) from Micheloud's article. I tried to get the emulator to start with the new custom image by giving it as a parameter in the emulator start-up, but without success. So I had to replace the original ramdisk.img with my custom one.

The original image is located in the ANDROID_SDK_ROOT/platforms/android-10/images/ folder.

Then I started the Android emulator and ran the following commands in the
ANDROID_SDK_ROOT/platform-tools/ folder:

adb.exe shell ls / (you should run this command until you get a proper list of files)
adb.exe shell mkdir -p /data/framework

adb.exe push PATH_TO_ANDROID_SDK_SCALA\config\framework\scala-actors.jar /data/framework
adb.exe push
PATH_TO_ANDROID_SDK_SCALA\config\framework\scala-collection.jar /data/framework
adb.exe push
PATH_TO_ANDROID_SDK_SCALA\config\framework\scala-immutable.jar /data/framework
adb.exe push
PATH_TO_ANDROID_SDK_SCALA\config\framework\scala-library.jar /data/framework
adb.exe push
PATH_TO_ANDROID_SDK_SCALA\config\framework\scala-mutable.jar /data/framework

After this I restarted the emulator, but for some reason the emulator couldn't load the scala libraries correctly. So I had to do this again with the Scala 2.8.1 configured into the SCALA_HOME variable. With these libraries the loading went a lot better, but I still got this weird error message: DexOpt: mismatch dep signature for '/data/dalvik-cache/data@framework@scala-library.jar@classes.dex'. Despite the message, the emulator worked alright.

Compilation times

with Proguardwithout Proguard (Scala:Provided)without Proguard and with lazyunpackagewithout Proguard with scala cc (fcs:false) and lazyunpack
mvn clean package 1 min 56 sec 35 sec27 sec 21 sec
mvn package 1 min 32 sec 25 sec24 sec 14 sec


If you want to try this too, I have provided the Scala libraries (2.8.1) and also the custom ramdisk.img here so you don't have to do as much work as I did to get this working.

Big thanks to:
Stéphane Micheloud for this exellent article http://lamp.epfl.ch/~michelou/android/emulator-android-sdk.

Jan Berkel for making a really clear and easy step by step tutorial on how to do the emulator customization http://zegoggl.es/2011/07/how-to-preinstall-scala-on-your-android-phone.html

Monday, July 11, 2011

Improve your maven android build speed

Here’s a nice way of shaving around 10 seconds off your average maven builds total time when building Scala Android applications.

You know the part when you need to unpack everything to have ProGuard go through all your classes to remove that extra fat. Well, even if you make a lot of changes to your code, most of the time is spent unpacking the libraries (Scala and Android mainly). And these libraries don’t change that often. So after you’ve done it once, and they have already been unpacked to your target directory, why do it again? Well, someone figured that out and now it’s added to maven-android-plugin in version 2.9.0-beta-5, so switch to that from 2.8.4 which is what you are probably using.

Then all you need to do is add the line:

<lazyLibraryUnpack>true</lazyLibraryUnpack>

under the <configuration> of your maven-android-plugin.

If this causes force closes on your device/emulator, check that your ProGuard settings are not too aggressive.

Wednesday, July 6, 2011

Andengine application with Scala

Let's take a look at how to make a simple application with Scala and Andengine. This is the quick and dirty conversion from Andengine ParticleSystemSimpleExample made with Java.

Folders
Folder paths are only for example and you can change them from the pom.xml.

/src/main/resources/ - all none code stuff
/src/main/resources/assets/ - folder that contains all loadable content
/src/main/scala - all code
/src/main/android -all android specific stuff (configured in the pom.xml)


You can get the Android specific content to the /src/main/android folder by creating an empty Android module with IntelliJ Idea. Then copy AndroidManifest.xml and the res folder from the generated module to the /src/main/android folder in your Maven project.

Android config
Set the executable applications package as well as the executable file name in AndroidManifest.xml

/src/main/android/AndroidManifest.xml
Give a proper name to your application
/src/main/android/res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">ParticleSystemSimple</string>
</resources>


Code

This is the good stuff, finally!

First create a proper package by right clicking the /src/main/scala folder


Next, create the Scala class. Right click the newly created package and select new -> Scala Class

package com.studfarm.example

import com.studfarm.example.ParticleSystemSimpleExample._

ParticleSystemSimpleExample {}



Create a companion object for the class. Companion objects are used to store all static methods and variables. An object is called a companion object when the object is in the same file with the class and has the same name as the class.


Add these to the companion object:


val CAMERA_WIDTH:Int = 720

val CAMERA_HEIGHT:Int = 480

Remember to import the companion object so you can use the static methods and variables more easily.

package com.studfarm.example

import com.studfarm.example.ParticleSystemSimpleExample._

class ParticleSystemSimpleExample {

}

object ParticleSystemSimpleExample {
val CAMERA_WIDTH:Int = 720
val CAMERA_HEIGHT:Int = 480
}

Next we need to inherit the BaseGameActivity. Add extends BaseGameActivity to your class and accept the import. Implement the following methods:
  • onLoadEngine:Engine
  • onLoadResources
  • onLoadScene:Scene
  • onLoadComplete
The easiest way to do the implementation is to right click the code region of the class and select generate (or just alt+insert) -> implement methods... -> select the methods.

Unfortunately the result is not clean and you'll need to add an override keyword in front of every def generated.

package com.studfarm.example

import org.anddev.andengine.ui.activity.BaseGameActivity

class ParticleSystemSimpleExample extends BaseGameActivity{

override def onLoadScene() = null

override def onLoadResources() {}

override def onLoadEngine() = null

override def onLoadComplete() {}
}

object ParticleSystemSimpleExample {

}
Next we'll implement the methods.

OnLoadEngine

When the program is loaded, show a text to the user and set the camera.

override def onLoadEngine:Engine= {
Toast.makeText(this, "Touch the screen to move the particlesystem.", Toast.LENGTH_LONG).show
this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT)
return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera));
}
onLoadResources

Loads all resources for the application/game

override def onLoadResources {
this.mTexture = new Texture(32, 32, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.mParticleTextureRegion = TextureRegionFactory.createFromAsset(this.mTexture, this, "gfx/particle_point.png", 0, 0);
this.mEngine.getTextureManager().loadTexture(this.mTexture);
}
particle_point.png is placed under /src/main/resources/assets/gfx/ folder

Create the Scene:
override def onLoadScene:Scene= {
this.mEngine.registerUpdateHandler(new FPSLogger());

val scene = new Scene(1);
val particleEmitter = new CircleOutlineParticleEmitter(CAMERA_WIDTH * 0.5f, CAMERA_HEIGHT * 0.5f + 20, 80);
val particleSystem = new ParticleSystem(particleEmitter, 60, 60, 360, this.mParticleTextureRegion);

scene.setOnSceneTouchListener(new IOnSceneTouchListener() {

override def onSceneTouchEvent(pScene:Scene, pSceneTouchEvent:TouchEvent):Boolean= {
particleEmitter.setCenter(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());
true;
}

particleSystem.addParticleInitializer(new ColorInitializer(1, 0, 0))
particleSystem.addParticleInitializer(new AlphaInitializer(0))
particleSystem.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE)
particleSystem.addParticleInitializer(new VelocityInitializer(-2, 2, -20, -10))
particleSystem.addParticleInitializer(new RotationInitializer(0.0f, 360.0f))

particleSystem.addParticleModifier(new ScaleModifier(1.0f, 2.0f, 0, 5))
particleSystem.addParticleModifier(new ColorModifier(1, 1, 0, 0.5f, 0, 0, 0, 3))
particleSystem.addParticleModifier(new ColorModifier(1, 1, 0.5f, 1, 0, 1, 4, 6))
particleSystem.addParticleModifier(new AlphaModifier(0, 1, 0, 1))
particleSystem.addParticleModifier(new AlphaModifier(1, 0, 5, 6))
particleSystem.addParticleModifier(new ExpireModifier(6, 6))

scene.getLastChild().attachChild(particleSystem)
});

return scene;
}
All done. Run the mvn clean package. You should now have a working application. You can test it with the Android emulator or with a real Android phone.


Quickly converting AndEngine examples to Scala

If you are anxious to get your first AndEngine application running on Scala but your Scala is a little rusty or you are just taking your first steps with Scala, Intellij IDEA offers a nice little feature.
After you have created a base project for yourself with all the necessities (Scala, Android and AndEngine), you can first:
  • import one of the AndEngine examples (written in java) to your project,
  • select the contents of the file,
  • create a new Scala class and
  • paste the contents you copied earlier to that file.
Here comes the nice surprise, you are greeted with the following popup:
image
Well damn right I do! The end result sure isn’t the beautiful functional programming you want to achieve, and it does need some minor adjusting but it sure is a fast way to kick start your AndEngine experience with Scala.

Sunday, July 3, 2011

Your first scala-android apk

Ok, so far we've done some basic stuff. Here's some more before we really get to the good stuff. This post only contains the configuration for getting Scala working with Android. The next tutorial is going to include all the configurations to get a proper Android application packaged with Maven.

To get your environment running, please check this post by Janne.

Ok, let's get to the interesting part. Combining Scala, Maven and Android SDK with a working development environment.

Properties

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>5</maven.compiler.source>
    <maven.compiler.target>5</maven.compiler.target>
</properties>

New dependencies
  • Android
  • Andengine (2d engine)
<dependencies>
    <dependency>
        <groupId>com.google.android</groupId>
        <artifactId>android</artifactId>
        <version>2.3.3</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.andengine</groupId>
        <artifactId>andengine</artifactId>
        <version>1.0</version>
    </dependency>
</dependencies>

Since the Andengine package is not included in any Maven repository, you'll need to add the file by hand:

mvn install:install-file -Dfile=path-to-andengine.jar/andengine.jar -DgroupId=org.andengine -DartifactId=andengine -Dversion=1.0 -Dpackaging=jar

You can download the Andengine file here.

Remember to set packaging to apk!
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>first-application</artifactId>
<version>1.0</version>
<packaging>apk</packaging>
<name>first-application</name>


Plugins
The Android plugin that handles the apk generation.

<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
    <artifactId>maven-android-plugin</artifactId>
    <version>2.8.4</version>
    <configuration>
        <sdk>
            <!-- Don't forget to set your ANDROID_HOME environment variable to your SDK directory! -->
            <path>${env.ANDROID_HOME}</path>
            <!-- Platform 10 is Android 2.3.3 -->
            <platform>10</platform>
        </sdk>
        <jvmArguments>
            <jvmArgument>-Xmx1024m</jvmArgument>
        </jvmArguments>
        <!-- All of these go into the /src/main/android/ directory, we don't
        want to polute the project root directory. -->
        <androidManifestFile>${project.basedir}/src/main/android/AndroidManifest.xml</androidManifestFile>
        <resourceDirectory>${project.basedir}/src/main/android/res</resourceDirectory>
        <assetsDirectory>${project.basedir}/src/main/android/assets</assetsDirectory>
        <nativeLibrariesDirectory>${project.basedir}/src/main/android/native</nativeLibrariesDirectory>
        <resourceOverlayDirectory>${project.basedir}/src/main/android/overlay</resourceOverlayDirectory>

        <deleteConflictingFiles>true</deleteConflictingFiles>
        <undeployBeforeDeploy>true</undeployBeforeDeploy>
    </configuration>
    <extensions>true</extensions>
</plugin>
Last  we need the most important plugin of them all, ProGuard. Without this  plugin the apk generation will fail since the Scala dependency will generate too  many files.
<plugin>
<groupId>com.pyx4me</groupId>
    <artifactId>proguard-maven-plugin</artifactId>
    <version>2.0.4</version>
    <executions>
        <execution>
            <phase>process-classes</phase>
            <goals>
                <goal>proguard</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <injar>android-classes</injar>
        <libs>
            <lib>${java.home}/lib/rt.jar</lib>
        </libs>
        <obfuscate>false</obfuscate>
        <options>
            <option>-keep public class * extends android.app.Activity</option>
            <option>-keep public class * extends android.app.Application</option>
            <option>-keep public class * extends android.app.Service</option>
            <option>-keep public class * extends android.content.BroadcastReceiver</option>
            <option>-keep public class * extends android.content.ContentProvider</option>
            <option>-dontskipnonpubliclibraryclasses</option>
            <option>-dontoptimize</option>
            <option>-printmapping map.txt</option>
            <option>-printseeds seed.txt</option>
            <option>-ignorewarnings</option>
        </options>
    </configuration>
</plugin>
With these settings you should be able to create a working development environment for Android development with Scala. Make a test run by running the following command: mvn package to see if the environment compiles.
Congrats! You have an Android application that does nothing.
Also, if you can't get things working with the tutorial, here's the pom.xml you can use to get your application to compile.
From my point of view getting Android, Scala and Maven working together is a real pain in the ass and I couldn't have done the configuration without the following tutorials:
http://www.scala-lang.org/node/345 (Scala with Maven) Thanks to the Scala community.
Building Android applications with Maven and IntelliJ 11/26/2010 Thanks to Christian Bauer for an exellent tutorial.
Also some more information from Proguard:
http://code.google.com/p/maven-android-plugin/wiki/ProGuard?spec=svn331

Saturday, July 2, 2011

Enable fast Scala compiler (fsc) on IntelliJ IDEA

Regular compilation with Scala compiler is really slow. Most of the time is spent compiling parts of Scala libraries, instead of your own code though. Solution is to use fsc (fast scala compiler), which is daemon that compiles the required Scala libraries on the first compilation, and stays in memory after that, so your subsequent compilations after a lot faster.

My first guess was to just click the checkbox “Use fsc” in the Scala plugin settings page. This alone only causes exceptions. You also need to create a Scala compilation server instance for yourself.

  1. Open the 'Edit (Run/Debug) Configurations' dialogimage
  2. Click on the [+] in left top corner of the window
  3. Select 'Scala Compilation Server' (should be near the end of the list) 
  4. Give the new launcher a name (e.g. 'my fsc server') and hit OK
  5. Press the Play icon to compile and run as usual.

Your second press of Play should be a lot faster!