Comparing Device Description Repositories
Posted onWeb 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:
Download OpenDDR-Simple-API zip package and unzip it.
From the resulting folder, install
bin/OpenDDR-Simple-API-1.0.0.24.jar
andlib/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
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 |
|
|
51Degrees.mobi |
|
|
OpenDDR |
|
|
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