Introduction to Widget Handset APIs in WAC 1.0

By Michał Jankowski

Introduction

In the brand new release of Opera Widgets Runtime for Android there are plenty of new exciting features, including support for the newly available Widget Handset APIs from the WAC initiative. These provide widgets with a greater level of device access previously only available to native applications. Using these new APIs we can take pictures, check GPS location, browse our address books, access accelerometer information, and even send SMS, MMS and E-Mail messages!

Where do I start?

The best place to start is to look at the widgets demo provided by the Opera Widgets Team. Examples given describe specific APIs and demonstrate functionality at the same time. You can find them pre-installed in the new release of Opera Widgets Runtime for Android. If you're interested in the nuts and bolts you also take a look at the W3C Widget Packaging and Configuration specifications, which WAC 1.0 is based upon.

There is also an another article available on this site, which takes you through building a complete functioning WAC Widget: Building a spirit level widget using WAC 1.0.

Using available objects

WAC talks about the use of <feature> elements, which are additional elements added to a config.xml file in order to provide information about what kind of APIs a widget wants to access. This allows the Widget Manager to inform users what the widget being installed is able to do. This alleviates potential privacy issues. For example, when you install a widget for browsing feeds you might get suspicious if it requests access to camera, messaging or geolocation.

A widget config.xml that makes use of WAC features looks something like this:

<?xml version="1.0" encoding="UTF-8"?>
<widget xmlns="http://www.w3.org/ns/widgets" xmlns:JIL="http://www.jil.org/ns/widgets1.2">
    <JIL:access localfs="true" />
    <name>Demo Widget</name>
    <icon>icon.png</icon>

    <feature name="http://jil.org/jil/api/1.1/widget" required="true"/>
    <feature name="http://jil.org/jil/api/1.1/multimedia" required="true"/>
    <feature name="http://jil.org/jil/api/1.1.2/camera" required="true"/>
</widget>

In this example, to use Camera we are referencing three features: Widget, Multimedia and Camera. This is because the Camera object is part of the Multimediacode> object, and Multimedia is part of the top-level Widget object. We need all three to use the Camera object.

Also, note the extra name space included in the document above: xmlns:JIL="http://www.jil.org/ns/widgets1.2". This is the JIL namespace, and is included so we can use some elements not defined by WAC. In this example we've added <JIL:access localfs="true" />, which means that my widget will have access to the local file system.

Available features

Every object defined by WAC has its unique feature URI to explicitly identify it in a <feature> element inside config.xml. Always remember that a WAC object might be part of another WAC object: we always have to include feature URIs for all parent objects as well. In order to find this information please have a look at the WAC 1.0 specification.

the available features are explained below.

Accelerometer

The AccelerometerInfo object can be used to get information from a device's accelerometer. We can read accelerations on three axes (X, Y, Z) using the following code:

Widget.Device.DeviceStateInfo.AccelerometerInfo.xAxis
Widget.Device.DeviceStateInfo.AccelerometerInfo.yAxis
Widget.Device.DeviceStateInfo.AccelerometerInfo.zAxis

The unit for returned values are m/s² (meters per second squared, the standard SI unit for acceleration). If you place your device flat on a table it should report -9,8 m/s² on the zAxis.

IMPORTANT: because acceleration information changes very quickly as the device is moved around, all values are retrieved and stored when you read the xAxis. This way you can be sure that all values are from the exact same moment, but you have to remember to always read the xAxis value first.

See the Building a spirit level widget using WAC 1.0 article for a real accelerometer example. you can also download a working accelerometer demo, with sources.

AudioPlayer

AudioPlayer is an object allowing us to control music playback, playing sounds over HTTP, HTTPS, RTSP or the file protocol. To play music (e.g. as background music for a game) we can do something simple like this:

Widget.Multimedia.AudioPlayer.onStateChange = function(state){
    if (state == 'opened'){
        Widget.Multimedia.AudioPlayer.play();
    }
}

Widget.Multimedia.AudioPlayer.open('http://.../file.mp3');

Apart from opening the audio player and starting playback, you can also stop and pause/resume playback. These are all very similar methods. Just remember that these calls are executed asynchronously so you need to define onStateChange callbacks to handle state changes of the player, when the following states occur:

  • opened – when an audio file is loaded successfully
  • playing – when playback has started, after calling play()
  • stopped – when playback has stopped, after calling stop()
  • completed – when playback has stopped after reaching the end of a track.
  • paused – when playback is paused

Download a working audio player demo, with sources.

Camera

The Camera object is arguably one of the most interesting WAC features. It allows us to take photos and provide real-time camera previews in your widget. For example we could create a widget to take photos and instantly sharing them on MyOpera or Flickr. The first thing we need to do to get a camera preview is to create an <object> element in which to render the preview (it has to be an <object> element.)

A simple index.html to do this could look like so:

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="js/camera.js"></script>
    <style type="text/css">
        #preview {
            width: 300px;
            height: 300px;
        }
    </style>
</head>
<body>
    <object id="preview"></object>
    <button id="shoot">take photo</button>
</body>
</html>

This will create a document containing a 300 x 300px preview window, and a button to press to capture an image.

Now for some JavaScript to handle the functionality - in the attached camera.js file we could write:


window.addEventListener('load',function(){

    //set preview window to #preview <object>
    Widget.Multimedia.Camera.setWindow(document.getElementById('preview'));

    //callback function called when taking photo succeeded
    Widget.Multimedia.Camera.onCameraCaptured = function(filename){
        alert(filename);
    }

    //setting button onclick event
    document.getElementById('shoot').addEventListener('click',function(){
        Widget.Multimedia.Camera.captureImage(null, false);
    }, false);

},false);

So, when this widget is run on a supporting device, it gives us a real time camera preview. When the “take photo” button is clicked, it will save the image in the default location (we can specify the desired path using the first parameter of the captureImage method) and call the onCameraCaptured callback function to display an alert containing the image path. We can display it in a widget using this path — we just need to remember to add file:// in front of it.

Download a working camera demo, with sources.

Position Info

The W3C Geolocation API is a very exciting spec allowing applications to access GPS information. It is however currently supported well across desktop browsers but not so reliably across mobile browers, and because of the processor limitations on mobile devices it seems counterproductive to use a whole separate API for this purpose. But never fear — we can access precise GPS position using the WAC 1.0 API. In order to get information describing the device's current position we need onPositionRetrieved and requestPositionInfo:

Widget.Device.DeviceStateInfo.onPositionRetrieved = function(position, method){
    /* … */
};

Widget.Device.DeviceStateInfo.requestPositionInfo('gps');

After calling the above function the device will get its position from the GPS if available: when the position is retrieved the callback onPositionRetrieved will be called. The position information will be contained in an object with following fields:

Name Type Description
accuracy Number The horizontal accuracy of the position in meters. Takes a value of null if the information is not available.
altitude Number the altitude in meters, using the World Geodetic System 1984 (WGS84) datum.
altitudeAccuracy Number The vertical accuracy of the position in meters. Takes a value of null if the information is not available.
cellID Number This is the id of the cell, defined when using GSM or AGPS.
latitude Number The latitude in degrees, using the World Geodetic System 1984 (WGS84) datum.
longitude Number The longitude in degrees, using the World Geodetic System 1984 (WGS84) datum.
timeStamp Date The time when the location data was established.

Using this information we could for example display our current position on a map. Download a working position Info demo, with sources.

Messaging

Using the WAC 1.0 API we can enable applications and widgets to send SMS, MMS and E-Mail messages. To do so we need to create a Message object that will represent the message, like so:

//prepare a callback method in case sending has failed
Widget.Messaging.onMessageSendingFailure = function(msg, error){
    alert(“Sending failed!\n”+error);
}

//choose message type
var messageType =  Widget.Messaging.MessageTypes.SMSMessage;

//create message
var message = Widget.Messaging.createMessage(messageType);

//set needed properties
message.addAddress('destination','phone number');
message.body = 'body can be any text';

//send message
Widget.Messaging.sendMessage(message);

Remember that our users may be charged by their carriers for sending messages depending on their plan and connection type. Sending E-Mail when connected through WiFi will be free but sending MMS probably will probably cost money. It sounds like an obvious point, but we should keep that in mind when developing applications, and make our users aware.

Download a working messaging demo, with sources.

Conclusion

The WAC 1.0 specification allows us to build more powerful Widgets and applications, with functionality more comparable to that of native apps. At Opera we are looking forward to seeing what you build using this new functionality. As always, let us know what you think, and feel free to make comments or ask for help on the Opera Widgets forums.

This article is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported license.

Comments

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

No new comments accepted.