Building a spirit level widget using WAC 1.0

By Michał Borek


The WAC initiative is a joint effort by mobile industry leaders to make mobile applications more interoperable across devices, easier for developers to create, and more powerful and useful for end users. It includes a community website containing useful resources, and the WAC 1.0 specification. This specification includes requirement lists for phones wanting to be able to support the spec, links to the W3C widget specs that WAC 1.0 is based on, and perhaps most interestingly, the Widget Handset APIs. The Handset APIs provide a means for developers to hook into device-specific features such as cameras, accelerometers, audio players and more.

And this last feature is what this article is about. Here we will show you how to use the WAC 1.0 AccelerometerInfo API to build a simple spirit level (or water level) Widget that measures how your phone is tilting on different axes, and displays this information in an familiar visual format, as seen in Figure 1.

a spirit level tool for a mobile phone, created using WAC 1.0 and packaged using a W3C Widget

Figure 1: A spirit level tool for a mobile phone, created using WAC 1.0 and packaged using a W3C Widget.

AccelerometerInfo, and the three phone axes

Our spirit level tool uses the AccelerometerInfo API to obtain information about the phone's acceleration in three different axes (see also Figure 2):

  • x: The right side of the phone
  • y: The top side of the phone
  • z: The front side of the phone

the three different axes of a phone for calculating tilt in different directions

Figure 2: The three different axes of a phone for calculating tilt in different directions.

Based on this three values you can calculate tilt in every direction. For example, When your phone lays on the table, the x value and y value are equal to 0 and the z value is near 9.81m/s². We will describe it later.

Building our Widget

In this section we will look at all the files involved in our widget. You can download the complete widget and play with it yourself. Please note that to run this widget successfully you need our Opera Widget runtime for Android with WAC support.

The config.xml file

If we want to use AccelerometerInfo to gain access to a phone's accelerometer we need to specify additional features in our widget's config.xml file. We must add AccelerometerInfo's dependencies — the widget, device and devicestateinfo API features — via <feature> elements to make it work properly:

<?xml version="1.0" encoding="UTF-8"?>
<widget xmlns="" height="320" width="240">
	<name>Level Tool</name>
	<feature name="" required="true" />
	<feature name="" required="true" />
	<feature name=""
		required="true" />
	<feature name=""
		required="true" />

Getting information from the accelerometer

When using AccelerometerInfo, all accelerometer values are accessed via the Widget.Device.DeviceStateInfo.AccelerometerInfo object and its three attributes xAxis, yAxis, zAxis. If you have already configured specific features, you can access accelerations as follows:

var accelerationX = Widget.Device.DeviceStateInfo.AccelerometerInfo.xAxis;
var accelerationY = Widget.Device.DeviceStateInfo.AccelerometerInfo.yAxis;
var accelerationZ = Widget.Device.DeviceStateInfo.AccelerometerInfo.zAxis;

There is one thing you must remember — the AccelerometerInfo object is updated when you read the xAxis value, so xAxis should always be read first, otherwise values won't be updated and you'll get old values.

The unit used for acceleration is m/s² (meters per second squared – standard under the SI metric system).

How does the spirit level tool work?

In our spirit level tool, acceleration is simply converted into the destination point of the bubble in UI. For example, if you hold phone the horizontally and then tilt it to right the x acceleration value will increase, so we need to move the left/right bubble to the left. The bigger the tilt, the bigger the distance between the center of the tube containing the bubbles, and the bubbles themselves. The position of each bubble is updated every 40 ms (approximately 24 times per second).

In every frame we use the all-important update() function to refresh all data (acceleration, bubble velocity, etc.):

function update() {
  destination.x = (accX - calibration.x) * maxAccRatio;
  destination.y = (accY - calibration.y) * maxAccRatio;
  velocity.x += ((destination.x - pos.x)/1.5 - velocity.x/5) * 40 * updateFactor;
  velocity.y += ((destination.y - pos.y)/1.5 - velocity.y/5) * 40 * updateFactor;
  move(velocity.x * updateFactor, velocity.y * updateFactor);

First we calculate where the bubble should be now — this is our destination. We assume that the force that makes bubble flow in a specific direction is proportional to the distance between the destination and the current position of a bubble and that there is a water viscosity proportional to speed of the bubble. The bubble won't move to destination point immediately, because of water viscosity, so we simulate that effect next. The last thing to do in each frame is move the bubble based on it's current velocity — done by the move function near the bottom of the above code snippet.

Note that there is a calibration object referenced above, which helps you correct accelerometer values. It's set by clicking the calibration button in the UI.

Now let's look at the updateAccelerometer() function referenced above. This function simply assigns specific acceleration values into shorter variables, so that they are easier to use later:

function updateAccelerometer() {
	accX = Widget.Device.DeviceStateInfo.AccelerometerInfo.xAxis;
	accY = Widget.Device.DeviceStateInfo.AccelerometerInfo.yAxis;
	accZ = Widget.Device.DeviceStateInfo.AccelerometerInfo.zAxis;


The spirit level tool is a nice example of a widget that takes advantage of the accelerometer features in the WAC specification. Please feel free to modify our example in any way you like to produce interesting new examples, and let us know what you think!

This article is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported license.


The forum archive of this article is still available on My Opera.

No new comments accepted.