Using Animations and Creating Custom Animations for Android
September 25th, 2010
Using animations in your Android applications can help create an interesting and engaging experience for your users. They can be used in games and applications in a number of ways either as a visual treat or as a method to convey information. Fortunately Android has an animation framework that allows you to easily translate, rotate, scale and alter the alpha of (or a combination) a View. Common transitions like fade in/out or slide in from off screen are examples of animations the framework can produce.
Animations and Interpolators
The process of animating a View makes use of two classes the Animation and Interpolator classes. The Animation class describes various aspects of the animation such as the transformation (changes in position, alpha, etc) and the duration of the animation.
The Interpolator class describes the rate of change of the animation, for example a ScaleAnimation with an AccelerateIterpolator results in a View that scales slowly at first and speeds up until the end of the animation. There are a number of different interpolators the most basic LinearInterpolator to more complex ones such as AccelerateInterpolator, AccelerateDecelerateInterpolter and OvershootInterpolator.
Adding Animation to a View
Here is res/layout/main.xml, it contains a button called ‘butt’ that is centred in the screen.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/butt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Shake!"/> </RelativeLayout>
Now we define our animation, res/anim/exampe_anim.xml , which is going to slide the button in from the bottom of the screen to the centre of the screen scaling from 0.5 to 1 as it travels all in 1.5 seconds. The p in 50%p means parent, since the Button is a primary child of the RelativeLayout this means 50% of the screen height.
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator" android:shareInterpolator="true"> <translate android:fromYDelta="50%p" android:toYDelta="0" android:duration="1500" /> <scale android:fromYScale="0.5" android:toYScale="1" android:fromXScale="0.5" android:toXScale="1" android:duration="1500" /> </set>
To start the animation use AnimationUtils.loadAnimation(context, resID) to load the animation and the startAnimation(animation) method of the View class.
butt.startAnimation(AnimationUtils.loadAnimation(getBaseContext(), R.anim.example_anim));
Using Custom Fonts in Android
June 23rd, 2010
Using a .ttf or .otf font in Android is fairly straightforward. Firstly create ‘assets/fonts/’ and put the files in there. Now using Typeface.createFromAsset we can create the typeface.
Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/CustomFont.ttf");
To set TextView to use this typeface we use the setTypeface function.
TextView tv = (TextView) findViewById(R.id.texty); tv.setTypeface(tf);
You can, of course, use this in your custom views with Paint.setTypeface.
Words of Warning
In general I wouldn’t recommend using fonts other than Droid font family apart from in games. That is because Ascender Corp specifically developed the Droid font family for optimal quality and readability on small screen devices. In an application the font is typically a form in which to present some information rather than containing information itself. For example in a racing you might use a font that is elongated with spoilers resembling a car but you probably would not use such a font for an article about cars.
Limitations
As far as I’m aware it is not possible to reference a font in XML. Making something like this impossible:
<TextView android:id = ”@+id/texty” android:typeface = "@font/CustomFont" />
I think that the Android team may have purposefully excluded a mechanism for referencing custom typefaces in XML to deter people from using an insane custom font that is difficult to read and potentially quite large.
On Android, and in general, you want your application or game to be responsive. So operations that take a long time to finish or block I/O should not be preformed on the UI thread otherwise the UI becomes clunky and unresponsive. To solve this problem any CPU intensive or I/O blocking operation are preformed in a separate thread. Unfortunately this creates another problem, which is how do we update and control the UI from this separate worker thread.
This is where Handlers come into play they allow you to send Messages (information and instructions) from the worker thread to the UI thread. A Message can contain ints using the fields arg1 and arg2 and an arbitrary Object using the obj or a Bundle using the setData(Bundle data) method.
So here’s an example of how to use Handlers:
public class DataView extends View {
final static int FAILURE = 123, DATA = 124;
DataHandler handler;
ArrayList data;
boolean failure = false;
public DataView(Context context, AttributeSet attrs) {
super(context, attrs);
handler = new DataHandler();
(new Thread(new WorkerRunnable(this))).start();
}
@Override
protected void onDraw(Canvas canvas) {
// draw something based on data…
}
private class DataHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case FAILURE:
failure = true;
invalidate();
break;
case DATA:
data = (ArrayList) msg.obj;
invalidate();
break;
default:
super.handleMessage(msg);
break;
}
}
}
@Override
public Handler getHandler() {
return handler;
}
}
public class WorkerRunnable implements Runnable {
private DataView dataView;
private ArrayList dataObjects = new ArrayList(10);
public WorkerRunnable(DataView dataView) {
this.dataView = dataView;
}
@Override
public void run() {
boolean success = true;
// some io or cpu heavy operations
Message msg = Message.obtain();
if(success){
msg.what = DataView.DATA;
msg.obj = dataObjects;
}else{
msg.what = DataView.FAILURE;
}
dataView.getHandler().sendMessage(msg);
}
}
Explanation
The DataView spawns a Thread that runs a WorkRunnables code, which performs some IO or CPU heavy operations. The WorkRunnable informs the UI once it has finished (or failed) by sending messages to the custom written Handler.
Simon!
June 14th, 2010
I have released my first Android game on to the Market. It is basically a copy of the classic electronic memory game Simon, a game in which you repeat the gradually lengthening computer generated sequence for as many rounds as you can. The game has multiple difficulty settings, musical notes and a colourful design.


The release of this game is more of an experiment to investigate how the Android Market works and game development on the platform works. Therefore the game itself is fairly unoriginal and took a short amount of time to produce but the graphics and game mechanics are of a high standard. The process has taught me some useful things about Android, for example how to use custom fonts and ‘Handlers’ to update the UI from a Thread other than the UI Thread. Both of which I shall write articles about.
Now on to my next Android project using all that I have learnt from this one.
Ideal Android Tablet
May 8th, 2010
The recent release of the iPad and announcement of the JooJoo a Linux based tablet, has inspired some want for a tablet device. But neither have great appeal; the iPad because of Apple’s megalomaniacal desire to fully control users mobile devices and the JooJoo’s clunky software not to mention the device itself is simply is too large.
Here is a pointless mock up of a device looking quite a lot like an iPad.

Dimensions and Display
The device would be about 7.5’’x11’’ and have a screen resolution of at least 720×1200 so that horizontally it can play 720p video without scaling. Also viewing the web or an e-book would not be strenuous or involve constant zooming and scrolling.
Operating System
Android would be the underlying operating system giving assess to a vast number of apps as well as high-quality ‘utility’ applications such as the browser and e-mail client.
Processor
The device would be powered by a 1GHz Snapdragon processor or similar possibly the upcoming 8X72 chipset. The 8X72 is capable of decoding 1080p video.
Output
Outputs include an HDMI port and a 3.5mm stereo jack. The combination of wi-fi and HDMI would allow streaming of high definition video to a HD TV. Acting like a network enabled set top box.
Maybe some day the perfect tablet with arrive but until that day I guess I’ll have to stick to reading an actual newspaper while munching on my cornflakes.
Android GPS Example
April 11th, 2010
For some reason there doesn’t seem to be a clear example showing how to use GPS on Android. Here is some code I have written that listens for location changes and displays the data in a TextView. The example also shows how to open the GPS setting with code via an Intent, since sometimes the GPS will be turned off by the user.
Code
package uk.co.hejp.GPSExample;
import android.app.Activity;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
public class Main extends Activity implements LocationListener {
/* this class implements LocationListener, which listens for both
* changes in the location of the device and changes in the status
* of the GPS system.
* */
static final String tag = "Main"; // for Log
TextView txtInfo;
LocationManager lm;
StringBuilder sb;
int noOfFixes = 0;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/* get TextView to display the GPS data */
txtInfo = (TextView) findViewById(R.id.textInfo);
/* the location manager is the most vital part it allows access
* to location and GPS status services */
lm = (LocationManager) getSystemService(LOCATION_SERVICE);
}
@Override
protected void onResume() {
/*
* onResume is is always called after onStart, even if the app hasn't been
* paused
*
* add location listener and request updates every 1000ms or 10m
*/
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10f, this);
super.onResume();
}
@Override
protected void onPause() {
/* GPS, as it turns out, consumes battery like crazy */
lm.removeUpdates(this);
super.onResume();
}
@Override
public void onLocationChanged(Location location) {
Log.v(tag, "Location Changed");
sb = new StringBuilder(512);
noOfFixes++;
/* display some of the data in the TextView */
sb.append("No. of Fixes: ");
sb.append(noOfFixes);
sb.append('\n');
sb.append('\n');
sb.append("Londitude: ");
sb.append(location.getLongitude());
sb.append('\n');
sb.append("Latitude: ");
sb.append(location.getLatitude());
sb.append('\n');
sb.append("Altitiude: ");
sb.append(location.getAltitude());
sb.append('\n');
sb.append("Accuracy: ");
sb.append(location.getAccuracy());
sb.append('\n');
sb.append("Timestamp: ");
sb.append(location.getTime());
sb.append('\n');
txtInfo.setText(sb.toString());
}
@Override
public void onProviderDisabled(String provider) {
/* this is called if/when the GPS is disabled in settings */
Log.v(tag, "Disabled");
/* bring up the GPS settings */
Intent intent = new Intent(
android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
@Override
public void onProviderEnabled(String provider) {
Log.v(tag, "Enabled");
Toast.makeText(this, "GPS Enabled", Toast.LENGTH_SHORT).show();
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
/* This is called when the GPS status alters */
switch (status) {
case LocationProvider.OUT_OF_SERVICE:
Log.v(tag, "Status Changed: Out of Service");
Toast.makeText(this, "Status Changed: Out of Service",
Toast.LENGTH_SHORT).show();
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
Log.v(tag, "Status Changed: Temporarily Unavailable");
Toast.makeText(this, "Status Changed: Temporarily Unavailable",
Toast.LENGTH_SHORT).show();
break;
case LocationProvider.AVAILABLE:
Log.v(tag, "Status Changed: Available");
Toast.makeText(this, "Status Changed: Available",
Toast.LENGTH_SHORT).show();
break;
}
}
@Override
protected void onStop() {
/* may as well just finish since saving the state is not important for this toy app */
finish();
super.onStop();
}
}
Permissions
Of course the Android framework has security permissions to protect the user. To get the permission to use GPS add a uses-permission tag with attribute android:name set to “android.permission.ACCESS_FINE_LOCATION” to the AndroidManifest.xml document as a direct child of the manifest tag, i.e:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Notes
When testing this code in the emulator, you can send mock fixes by connecting to the emulator using telnet, i.e. ‘telnet localhost 5554′ and typing:
geo fix -10.223, 40.549
Android Example Sensor Application
August 7th, 2009
In this example data from the accelerometer is written to a TextView (Android TextArea), this example could easily be altered to use anyone of the other sensors (temperature, light, pressure, etc).
package hejp.AccelerometerExample;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import android.hardware.SensorManager;
import android.hardware.SensorEventListener;
import android.hardware.SensorEvent;
import android.hardware.Sensor;
import java.util.List;
public class AccelerometerExample extends Activity {
SensorManager sm = null;
TextView accText = null;
List list;
/* This responds to sensor events */
SensorEventListener sel = new SensorEventListener(){
public void onAccuracyChanged(Sensor sensor, int accuracy) {
/* Isn't required for this example */
}
public void onSensorChanged(SensorEvent event) {
/* Write the accelerometer values to the TextView */
float[] values = event.values;
accText.setText("x: "+values[0]+"\ny: "+values[1]+"\nz: "+values[2]);
}
};
/* Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/* Get a SensorManager instance */
sm = (SensorManager)getSystemService(SENSOR_SERVICE);
/* This corresponds to a TextView element in main.xml with android:id="@+id/accText" */
accText = (TextView)findViewById(R.id.accText);
/* Get list of accelerometers */
list = sm.getSensorList(Sensor.TYPE_ACCELEROMETER);
/* If there are any accelerometers register a listener to the first else
print a little error message */
if(list.size()>0){
sm.registerListener(sel, list.get(0), SensorManager.SENSOR_DELAY_NORMAL);
}else{
Toast.makeText(getBaseContext(), "Error: No Accelerometer.", Toast.LENGTH_LONG);
}
}
@Override
protected void onStop() {
/* Always a good idea to unregister, disconnect, close, etc things */
if(list.size()>0){
/* This actually unregisters a listener for all sensors, but it can be done
on a sensor by sensor basis */
sm.unregisterListener(sel);
}
super.onStop();
}
}
Personally I think that Android is the most interesting and significant mobile platform ever. The fact that it’s open and it’s level of functionality, not to mention it’s backed by Google, make it like nothing else.
Having had written mobile applications (in Java) before and enduring the seemingly endless interoperability problems and senseless security restrictions (for example bluetooth PSM restrictions making to impossible to connect to a wiimote) makes this a real excitement.
