Using the Accelerometer for cool apps in JavaME
This article explains how to properly use the accelerometer for effects and user interaction for apps.
Article Metadata
Code Example
Tested with
Compatibility
Article
Introduction
With the new Asha Full Touch devices coming with JSR-256 and an accelerometer support you can explore new ways to use that feature for cool effects or user-interaction for you apps. In this Example i will show how to create a dice app that will start to roll once the phone is shaked. You can check out the full app also on the Nokia store.
The code
The code is split into 5 classes
- Dice - a domain class this represent a single die, it has the x,y position as well as the current state of the die (moving,rolling) it also has all the strips of the die sides.
- DirectionSensor - this utility class is responsible to listen to the accelerometer x,y,z axis and calculate the difference between the current and former x,y,z state and if the difference is large enough it send a message to ShakeListener
- Main - The MIDLet class
- MyCanvas - This class inherits the GameCanvas class and calls the paint() method of dice, its also responsible for the collision detection of the dice.
- Rect - This is a simple utility class to do collision test between 2 rects.
I'll post below parts of the code for the DirectionSensor class and Main class which both relates to the topic of this article which is the use of the accelerometer, for the full source code of all the class you can downloaded the attached source project.
DirectionSensor class - 3 important methods. dataReceived(SensorConnection con, Data[] dataArray, boolean isDataLost) - this method is needed in order to implements the DataListener of SensorConnection it calls getIntegerDirection to convert the raw buffer data to x,y,z values it can work it. It also compare the current values magnitude with the previous values magnitude and detects if a shake has occurred.
public void dataReceived(SensorConnection con, Data[] dataArray, boolean isDataLost)
{
if (dataArray == null) {
return;
}
if (dataArray.length < 3) {
return;
}
double temp[] = getIntegerDirections(dataArray);
if (!receivedFirstData)
{
receivedFirstData = true;
acceleration[0] = (float) temp[1];
acceleration[1] = (float) temp[0];
acceleration[2] = (float) temp[2];
return;
}
else
{
if (Math.abs(vectorMagnitude(new float[]{(float) temp[1],(float) temp[0],(float) temp[2]})-vectorMagnitude(acceleration))>DIRECTION_DELTA)
{
acceleration[0] = (float) temp[1];
acceleration[1] = (float) temp[0];
acceleration[2] = (float) temp[2];
listener.shakeStarted();
return;
}
else
{
acceleration[0] = (float) temp[1];
acceleration[1] = (float) temp[0];
acceleration[2] = (float) temp[2];
return;
}
}
}
vectorMagnitude(float[] arr) - this is a helper function to calculate a 3d vector's magnitude - the x,y,z values of the accelerometer can be think of as 3d vector and you can calculate its magnitude and compare it to another 3d vector magnitude and if the difference between the two magnitudes are bigger than delta then the movment was big.
double[] getIntegerDirections(Data[] data) - this function converts the raw Data buffer to x, y, z float values to work with.
private static double[] getIntegerDirections(Data[] data)
{
double [][] intValues = new double[3][BUFFER_SIZE];
double[] directions = new double[3];
for (int i=0; i<3; i++){
intValues[i] = data[i].getDoubleValues();
double temp = 0;
for (int j = 0; j<BUFFER_SIZE; j++) {
temp = temp + intValues[i][j];
}
directions[i] = temp/BUFFER_SIZE;
}
return directions;
}
Main class - its important code is inside its startApp method, its main purpose is to create and find the proper sensor and its connection for use. Note that we SensorManager.findSensors("acceleration", null) can return several SensorInfo so you need to make sure you get the right one. In the example below we search for an acceleration sensor that support the reporting of Double values as its data type.
protected void startApp() throws MIDletStateChangeException
{
try
{
Display.getDisplay(this).setCurrent(canvas);
canvas.startRendering();
sensor = null;
SensorInfo infos[];
infos = SensorManager.findSensors("acceleration", null);
int datatypes[] = new int[infos.length];
int i = 0;
String sensor_url = "";
boolean sensor_found = false;
while (!sensor_found) {
datatypes[i] = infos[i].getChannelInfos()[0].getDataType();
if (datatypes[i] == ChannelInfo.TYPE_DOUBLE) {
sensor_url = infos[i].getUrl();
sensor_found = true;
}
else i++;
}
sensor = new DirectionSensor((SensorConnection) Connector.open(sensor_url));
sensor.activate(this);
} catch (Exception e)
{
e.printStackTrace();
notifyDestroyed();
}
}
As you can see in the Main startApp() method we ask the SensorManager for an accelerometer sensor and then we traverse the returned array and search for a sensor that supports channel type Double (sensor can support different channel types which is basically the way the data is transeferred back to you Double/Int).
In the DirectionSensor class the two main important methods are dataReceived(SensorConnection con, Data[] dataArray, boolean isDataLost) and getIntegerDirections(Data[] data) in the first method we call the second method to interpret the raw values from the sensor and then we calculate the different between its current and its previous state (this is done with a simple math calulation of the magnitude of the x,y,z vector)
Summary
I hope you download the binary and test out the app yourself and then check out the code to learn how to make more cool apps like this.


Contents
Hamishwillee - Thanks!
Hi Shaii
Thanks very much. IMO this is better presented than the others because there is more explanation of what the code is doing and where, and because you've provided an overview of the main classes.
In terms of improvement you could probably go further and split this code into smaller sections with the relevant parts highlighted immediately alongside the explanation - usually I like explanation of code first. However it is acceptable as is because the code is not particularly hard to understand, and the code explanation isn't all that far away.
I would prefer a title that said something like "Using the accelerometer sensor to shake dice in Java ME". This is an accurate and objective description of what the article covers, and leaves the user the opportunity to decide whether the article is cool or not :-).
Regards
Hamishhamishwillee 09:44, 1 August 2012 (EEST)
-Pekkeli- - Thanks!
Hi,
thanks for the code example!
Do you know if it is possible to access accelerometers under lock screen?
Cheers,
Pekka-Pekkeli- 11:59, 3 August 2012 (EEST)
Shaii - Hi Pekkeli
I'm sorry i havent tried it but you can easily try it, just download the attached app and give it a tryshaii 16:06, 7 August 2012 (EEST)
Hamishwillee - @Pekkeli
Hi Pekka
Did it work - might be nice to let Shai know :-)
regards
Hhamishwillee 10:29, 3 September 2012 (EEST)
-Pekkeli- - @Hamishwillee & @Shaii
Hi,
I do not own Asha phone, so I have not tried. However, I yesterday found out about remote device access (http://www.developer.nokia.com/Devices/Remote_device_access/). Maybe I try using that when I have time. :)
Cheers,
Pekka-Pekkeli- 08:25, 18 October 2012 (EEST)
-Pekkeli- - @Hamishwillee & @Shaii
Hi,
accelerometers do work perfectly also under lock screen!-Pekkeli- 16:09, 5 December 2012 (EET)
Hamishwillee - Pekkeli - Thanks very much for the update
Much appreciated. Shai, if it can be done reasonably, might be worth including this information within the article itself.hamishwillee 02:00, 7 December 2012 (EET)
Hamishwillee - What permissions are required for certification?
Hi Shai
What permissions are required? Would be great to add.
Regards
Hhamishwillee 04:28, 26 April 2013 (EEST)