Live Wallpapers part 1 – Animated Live Wallpaper

Live wallpapers serve up an impressive introduction to Nexus Ones. Introduced in Android 2.1, these dashboard backgrounds have the advantage of being able to interact with a device programatically.  To celebrate receiving our Nexus Ones at a Londroid / Google Android developer lab have excitedly created some quick LiveWallpapers demos we’d like to share.

Animated LiveWallpaper

Live Wallpapers offer unique screen real estate over widgets and a chance to show off some dashboard visuals. Childhood memories have instilled a message of freedom into the image of a Testerrossa speeding down an open road with a pretty girl ala “Ferris Buellers day off” and Sega’s classic “Outrun”. So What better to express the open platform than an OutRun inspired Live Wallpaper?

A sexy implementation using the openly available github source code:

Download the outrun livewallpaper for the Nexus One
Scenery changes every time the phone is sleeping as you can see here, here and here, in awful quality.

Admittedly my graphics aren’t quite as inspiring.

Demo graphics

Download Demo apk compiled for a Nexus One

Animated LiveWallpaper Notes

Src code for Demos projects on Github:
Switch Image on left/right
Switch Animation on left/right

A Live Wallpaper consists of an ‘Engine’ and a ‘Service’. The engine specifies how your wallpaper is rendered while it’s service creates instances for the home screen. A wallpaper service differs from a normal service in addition of  OnEngineCreate(). This has been the first time I’ve used the canvas extensively and I learned you first must lock the canvas and choose which region you wish to redraw. onVisibilityChanged() or onSurfaceChanged() will read much like the instructions of how to draw your canvas from empty. Onvisibility() will first change to true in rendering your wallpaper  preview and this will return false when your wallpaper falls out of view and you transition to your dashboard. This is a handy function as every time your wallpaper falls out of view you can stop everything you are doing and free up the associated resources.

To update the drawn canvas state you need to tell the UI to refresh via a handler. In my case I needed to request an indexed image from within an collection upon each draw, Each time the handler returns back I update my drawn bitmap with a frame from the animation. It should be noted here that you should only be keeping the image Resource IDs in memory rather than the actual binary contents of the images. I was at first doing this, following a demo I downloaded but I soon ran into this error at runtime:

ERROR/AndroidRuntime(1067):
Uncaught handler: thread main exiting due to uncaught exception
java.lang.OutOfMemoryError: bitmap size exceeds VM budget

This is because all of the png images although starting out quite small, when transformed to bitmaps upon interpreation they become a lot larger and quickly fill up the allotted memory allocation. Instead I just kept an array of resIds using res.getIdentifier(). This seems pretty good in the performance stakes.

I chose to play an animation for left and right steering when a user flicks between panels. I kept track of this via the onTouchEvent()’s ACTION_DOWN and then checking which side of the screen their ACTION_UP was upon. The reason I added a timer in there was to add a little delay for the animation so you can appreciate the perfect driving line of the Testerossa.An area that I would like to return to is recognising when the user’s finger has dragged the screen a certain distance. My original approach to recognising significant drag was to monitor the start and end points and see if they lay at different sides of the screen, I have since learned measuring the distance within onOffSetsChanged would probably be a more reliable approach.

The last thing of note with Live Wallpapers is that they have a convenience listener for dropping icons and tapping on the dashboard screen via sendWallpaperCommand() and then acting on the input via onCommand(), these could also be very useful and are used to good effect in the demos with water droplets and colours.

At the moment it seems like the wallpaper is a bit of a memory hog and I’d like to find out why. Any suggestions are appreciated.
We think that the problem is in the BitmapFactory.decodeResources() function recreating the Bitmap every time. In order to get around this I think the best way would be to create a ’spriteSheet’ then move around the area of this big sheet masking it to only the area I need like one of those revolving wheels that show the horse running. Live and learn, I always wondered why people used sprite sheets in games programming I guess this must be one of the reasons.

As a side note, if anyone has any information on how The Nexus One splash screen is able to read in it’s splash screen consisting of 97pngs (/system/media/bootanimation.zip) I’d love to hear how they achieved this. When developing ideas for your Live Wallpapers consider trying to include the interaction of forces particular to the context of a mobile device such as time, movement and position.

Android SDK at time of writing was: android-sdk-mac_x86-2.1 ( SDK version 7 )

Citations & Research

1 Comment

Scala on Android

The Scala Programming Language:

The Scala programming Language is an object oriented functional programming language designed to run on the JVM. It is ideal for programming on the Dalvik Platform as code written with the Scala language is more compact, readable and could possibly have performance benefits (which will be analysed at a later date) and it also supports Java and Android APIs.

You can easily build DSL with Scala and the trait (e.g. mixin) aspect of Scala is very attractive in order to build intricate activities which mixes different logic.

Requirements:

  • Eclipse IDE – Galileo Classic v3.6
  • Android ADT plugin v0.93
  • Android SDK v1.6r1
  • Scala eclipse plug-in latest
  • Scala-android library latest


Step 1: Setting up the environment

The Scala project is rather heavy on resources therefore we would need to increase the heap size of the eclipse VM and of the dx tool which is present in the SDK.

Editing the eclipse memory size:

In order to increase the maximum permissible memory of the IDE we need to edit the exlipse.ini file that resides in the root folder of the IDE (in my case C:/Program Files/eclipse or /opt/eclipse). Open the file with your favourite text editor and edit the files as shown in the figure below and add the following lines to the file:

256m
-vmargs
-Xms256m
-Xmx1024m
-XX:PermSize=64m

Editing dx.bat/dx.sh:

The file dx.bat/dx.sh is located in the <ANDROID_HOME>\platforms\android-1.6\tools. Open dx.bat/dx.sh with your favourite text editor and uncomment the javaOpts line while changing the value to 512M:

Step 2: Install Scala

I installed both the stand alone Scala installer as well as the Eclipse IDE plugin, which I recommend to get the system working stable.

The Scala Installer:

On writing this post the latest version of Scala available for download was the 2.7.6 version, which can be downloaded from: http://www.scala-lang.org/downloads/distrib/files/scala-2.7.6.final-installer.jar . The installation procedure is quite trivial and further information can be found on the Scala website. The installer consists of a sequence of simple steps which on completion result in the installation of Scala on your system.

Eclipse Plugin:

In order to install the eclipse plugin we have to goto the Help->Install New Software->Add and then enter the following:

Name: Scala
Location: http://www.scala-lang.org/scala-eclipse-plugin

You should then see “Scala Eclipse Plugin” offered for installation. Click on the “Install” button and follow the instructions from there.

Step 3: Download scala-android.jar

Open a new shell prompt window in administrator mode. Navigage to the <SCALA_HOME>/bin directory defined in the previous Scala installation step. Then enter the following commands

sbaz install scala-android

The scala-android library will be installed in <SCALA_HOME>/lib directory.

Step 4: Creating a Scala Project

In order to create our first Scala project we go about creating first an Android Project in the Eclipse IDE (File->New->Android Project).

Then right mouse click on the project in the package workspace and navigate down to the Scala menu, then click on Add Scala Nature, once this is completed the project would look like:


Once this is complete, right mouse click on the project again and click on the Properties->Builders tab, and make sure the Scala Builder is in the position as shown in the figure (you will have to move it down two places)

Then open the Java Build Path->Libraries tab and remove the Scala Library Version 2.6 final , then add the scala-android.jar file by click on Add External Jar. You will then have the menu resembling:

Note: The build process needs to compile the scala files into classes which then compiles them into dex files. If you receive errors upon compilation or classpath, try to clean and rebuild the project.

Step 5: Creating ScalaTest.scala

Now goto the ScalaTest->src->com.scala package and delete the the file ScalaTest.java. Right mouse click on the package and then click on New->Other-Scala Class , call this class ScalaTest.

Open the file ScalaTest.scala and enter the following code and save it:

package test.scala
import android.app.Activity
import android.os.Bundle
import android.widget.TextView
class ScalaTest extends Activity {
override def onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
val tv = new TextView(this)
tv.setText("Hello Android, it's me, Scala!")
setContentView(tv)
}}

Step 6: Running the application

In order to run the application goto Run->Run Configuration->Android Application and run set it up as shown in the figure below, and then click on Run.

If everything was set up right you’d then see the emulator load up and run your application

:

References:

  • http://www.scala-lang.org/node/160
  • http://www.ibm.com/developerworks/opensource/library/os-eclipse-scala/index.html?ca=dgr-jw64Android-Scaladth-o&S_TACT=105AGY46&S_CMP=grjw64#
  • http://www.scala-lang.org/node/1403
2 Comments