Web content delivered to mobile devices can benefit from being tailored to take into account a range of factors such as screen size, markup language support and image format support. Such information is stored in “Device Description Repositories” (DDRs).

Until recently WURFL was the de facto DDR standard for mobile capabilities, but its license changed to AGPL (Affero GPL) v3, meaning it is not free to be used commercially anymore. Consequently some free open source alternatives to WURFL have recently started to show up and are improving quickly.

OpenDDR and 51Degrees.mobi are candidate substitutes to WURFL that also provide an API to access DDRs.

These tools ease and promote the development of Web content that adapts to its delivery context. This post summarizes the installation and configuration of these tools and analyzes how they compare in terms of image adaptation.

The source code used for this post is available on GitHub.

Build configuration

This section describes how to add the dependencies to a Maven project.

WURFL

WURFL is really straightforward since it is available on Maven central repository. All you have to do is to include the dependency on your project:

<dependency>
    <groupId>net.sourceforge.wurfl</groupId>
    <artifactId>wurfl</artifactId>
    <version>1.2.2</version><!-- the latest free version -->
</dependency>

51Degrees.mobi

51Degrees.mobi configuration is very similar to WURFL. Just add the dependency to your project’s pom.xml file:

<dependency>
    <groupId>net.sourceforge.fiftyone-java</groupId>
    <artifactId>51Degrees.mobi.detection.core</artifactId>
    <version>2.2.9.1</version>
</dependency>

OpenDDR

OpenDDR is a bit harder to configure. Follow these steps to include OpenDDR in your project:

  1. Download OpenDDR-Simple-API zip package and unzip it.

  2. From the resulting folder, install bin/OpenDDR-Simple-API-1.0.0.24.jar and lib/DDR-Simple-API.jar into your local Maven repository:

    $ mvn install:install-file -DgroupId=org.w3c.ddr.simple -DartifactId=DDR-Simple-API -Dversion=2008-03-30 -Dpackaging=jar -Dfile=DDR-Simple-API.jar -DgeneratePom=true -DcreateChecksum=true
    $ mvn install:install-file -DgroupId=org.openddr.simpleapi.oddr -DartifactId=OpenDDR-Simple-API -Dversion=1.0.0.24 -Dpackaging=jar -Dfile=OpenDDR-Simple-API-1.0.0.24.jar -DgeneratePom=true -DcreateChecksum=true
    
  3. Add the dependencies to your project pom.xml file:

    <dependency>
        <groupId>org.w3c.ddr.simple</groupId>
        <artifactId>DDR-Simple-API</artifactId>
        <version>2008-03-30</version>
    </dependency>
    <dependency>
        <groupId>org.openddr.simpleapi.oddr</groupId>
        <artifactId>OpenDDR-Simple-API</artifactId>
        <version>1.0.0.24</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-jexl</artifactId>
        <version>2.1.1</version>
    </dependency>
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.6</version>
    </dependency>
    

Loading repository/capabilities file

This section describes how to load repository files and import them into your project.

WURFL

Copy wurfl-2.1.1.xml.gz file (the latest free version) into your project src/main/resources folder and import it using:

WURFLHolder wurflHolder = new CustomWURFLHolder(getClass().getResource("/wurfl-2.1.1.xml.gz").toString());

51Degrees.mobi

51Degrees.mobi does not use a separate repository file.

OpenDDR

Copy oddr.properties from the OpenDDR-Simple-API src folder and all files inside OpenDDR-Simple-API resources folder into your project src/main/resources folder. Import them using:

Service identificationService = null;
try {
    Properties initializationProperties = new Properties();
    initializationProperties.load(getClass().getResourceAsStream("/oddr.properties"));
    identificationService = ServiceFactory
            .newService("org.openddr.simpleapi.oddr.ODDRService",
                    initializationProperties.getProperty(ODDRService.ODDR_VOCABULARY_IRI),
                    initializationProperties);
} catch (IOException e) {
    LOGGER.error(e.getMessage(), e);
} catch (InitializationException e) {
    LOGGER.error(e.getMessage(), e);
} catch (NameException e) {
    LOGGER.error(e.getMessage(), e);
}

Using the API

This section describes how use WURFL and OpenDDR Java APIs to access the device capabilities.

WURFL

WURFL API is very easy to use and has the greatest advantage of providing a powerful fallback hierarchy, inferring capabilities for devices not yet in its repository file.

Device device = wurflHolder.getWURFLManager().getDeviceForRequest(getContext().getRequest());
int resolutionWidth = Integer.valueOf(device.getCapability("resolution_width"));
int resolutionHeight = Integer.valueOf(device.getCapability("resolution_height"));

There’s no need to validate device.getCapability("resolution_width") against null value when no data is available.

51Degrees.mobi

Similarly to OpenDDR, 51Degrees.mobi does not provide a fallback hierarchy. The developer must always validate each property value.

// Create a Provider object
Provider provider = Reader.create();

// Read in a User Agent String
BaseDeviceInfo deviceInfo = provider.getDeviceInfo(request.getHeader("User-Agent"));

// Get the value of a property
Integer screenPixelsWidth = 320; // Default value
Integer screenPixelsHeight = 480; // Default value
try {
    screenPixelsWidth = Integer.valueOf(deviceInfo.getFirstPropertyValue("ScreenPixelsWidth"));
} catch (NumberFormatException e) {
}
try {
    screenPixelsHeight = Integer.valueOf(deviceInfo.getFirstPropertyValue("ScreenPixelsHeight"));
} catch (NumberFormatException e) {
}

OpenDDR

OpenDDR API is very cumbersome. It does not have a fallback hierarchy, instead it assumes 800px as the default value for displayWidth and 600px as the default value for displayHeight.

PropertyRef displayWidthRef;
PropertyRef displayHeightRef;

try {
    displayWidthRef = identificationService.newPropertyRef("displayWidth");
    displayHeightRef = identificationService.newPropertyRef("displayHeight");
} catch (NameException e) {
    throw new RuntimeException(e);
}

PropertyRef[] propertyRefs = new PropertyRef[] { displayWidthRef, displayHeightRef };
Evidence evidence = new ODDRHTTPEvidence();
evidence.put("User-Agent", getContext().getRequest().getHeader("User-Agent"));

int displayWidth = 320; // Default value
int displayHeight = 480; // Default value
try {
    PropertyValues propertyValues = identificationService.getPropertyValues(evidence, propertyRefs);
    PropertyValue displayWidthProperty = propertyValues.getValue(displayWidthRef);
    PropertyValue displayHeightProperty = propertyValues.getValue(displayHeightRef);

    if (displayWidthProperty.exists()) { // Don't really need to validate. Returns 800 as the default value.
        displayWidth= displayWidthProperty.getInteger();
    }
    if (displayHeightProperty .exists()) { // Don't really need to validate. Returns 600 as the default value.
        displayHeight = displayHeightProperty.getInteger();
    }
} catch (NameException e) {
    throw new RuntimeException(e);
} catch (ValueException e) {
    throw new RuntimeException(e);
}

Results

The following table shows the results of the tests run against an application for server-side image adaptation. The tests were performed on real physical devices.

Feel free to run the tests for yourself using the source code available on GitHub.

Platform Device Property WURFL max_image_width(1) / max_image_height WURFL resolution_width / resolution_height 51Degrees.mobi ScreenPixelsWidth / ScreenPixelsHeight OpenDDR displayWidth / displayHeight
Windows Firefox desktop width 600 640 Unknown 800
height 600 480 Unknown 600
iOS iPhone 4S width 320 320 320 320
height 480 480 480 480
Android Samsung Galaxy S II width 240 240 480 480
height 320 320 800 800
HTC One V width 600 640 480 480
height 600 480 800 800
HTC Hero width 300 320 320 320
height 460 480 480 480
Windows Phone 7.5 Nokia Lumia 710 width 600 640 480 480
height 600 480 800 800
BlackBerry BlackBerry Bold 9900 width 228 480 640 640
height 280 640 480 480
Symbian S60 Nokia E52 (Webkit) width 234 240 240 240
height 280 320 320 320
Nokia E52 (Opera Mobile) width 240 240 Unknown 800
height 280 320 Unknown 600
Bada 2.0 Samsung Wave 3 width 600 640 480 480
height 600 480 800 800
Windows Mobile 6.1 HTC Touch HD T8282 width 440 480 480 480
height 700 800 800 800

(1) max_image_width capability is very handy:

Width of the images viewable (usable) width expressed in pixels. This capability refers to the image when used in “mobile mode”, i.e. when the page is served as XHTML MP, or it uses meta-tags such as “viewport”, “handheldfriendly”, “mobileoptimised” to disable “web rendering” and force a mobile user-experience.

Pros and Cons

  Pros Cons
WURFL
  • Upgradable to newer versions by only replacing its database file.
  • A Device Hierarchy that yields a high-chance that the value of capabilities is inferred correctly even when the device is not yet recognized.
  • Lots and lots of capabilities.
  • Very easy to configure.
  • Clean API.
51Degrees.mobi
  • Has a Lite version licensed under the Mozilla Public Licence, free to use, even commercially.
  • Easier to install and configure than OpenDDR.
  • Decent list of capabilities.
  • Even though the list of capabilities is better than OpenDDR's it still cannot compete with WURFL's.
OpenDDR
  • Free to use, even commercially.
  • Growing community.
  • Limited capabilities. OpenDDR seems to be limited to W3C DDR Core Vocabulary.
  • Returns 800 for displayWidth and 600 for displayHeight when the User-Agent does not exist in its database. It should let the developer choose which values result better for each particular application.

Let me stress how advantageous is to be able to upgrade WURFL by just replacing its XML database file. For the changes to take effect, there is no need to restart the application server or change the application source code. WURFL is also the only one supporting Opera Mobile browser.

Ending note

Keep in mind that while OpenDDR and 51Degrees.mobi test results may improve over time as I update the tests to use newer versions of them, WURFL will not be updated due to its new restrictive license. However, if a DDR solution is crucial to your business, you should really consider new versions of WURFL. It has improved a lot since the version used in this post making it is probably the best DDR money can buy.

Comments

comments powered by Disqus