Print

Creating Web Content for Mobile Phone Browsers, Part 2
Pages: 1, 2

The WURFL

The Wireless Universal Resource File (WURFL) project is a brave attempt to do exactly this, with the database taking the form of a XML file. The WURFL is an open source effort guided primarily by Laszlo Nadai, Luca Passani, and Andrea Trasatti, but relying on the community at large to ensure it is complete and accurate. Currently it tracks more than 100 features across more than 400 devices. That is a lot of information to maintain or to search through. The creators of the WURFL were smart and realized two important things: first, that contemporary phones from a given manufacturer tend to be very similar to each other, so that for many purposes, all you need is a single profile for that family of devices. Second, that most developers will not tailor their response down to the fine detail of each phone. Just knowing the main feature set and the screen size is sufficient for most of us.



Accordingly, the WURFL structures its data into a hierarchy that has a generic profile at its root. This allows developers some flexibility to choose what level of detail they want to deal with, as well as the possibility to infer the features of a phone that is not in the WURFL, based on part of the text in the User Agent header.

The innards of the WURFL itself are not for the faint-hearted. Fortunately, there are access libraries for Perl, PHP, .NET, and Java. The following code illustrates its use in Perl using the WURFLLite.pm module from Rainier Hillebrand, available at webcab.de/WURFL.

#!/usr/bin/perl -w -I.

# wurfl.cgi

# Based on the programming examples for WUFLLite.pm written
# by Rainer Hillebrand, rainer.hillebrand@webcab.de.
# The latest version can be found at:  http://webcab.de/WURFL/

use CGI;
use WURFLLite;

my $cgi = new CGI;

my $ua = $cgi->http('HTTP_USER_AGENT');

my %wurfl;
my $content = '';

open INPUT, "< ./wurfl.xml";
while (<INPUT>) { $content .= $_;} 
close INPUT;

parseXML(\%wurfl, \$content);

# Search for the User Agent and return the device ID

my $best_device_id = '';
my $best_user_agent = '';
my $best_ua_length = 0;

my $device_id = '';

foreach my $device_id (keys %{$wurfl{'devices'}}) {

   my $dev_user_agent =
     $wurfl{'devices'}->{$device_id}->{'attributes'}->{'user_agent'};

   if(not defined $dev_user_agent or $dev_user_agent eq '') {
	next;
   }

   if( $ua =~ m|^\Q${dev_user_agent}\E| and
       length($dev_user_agent) > $best_ua_length) {
       $best_device_id  = $device_id;
       $best_user_agent = $dev_user_agent;
       $best_ua_length  = length($dev_user_agent);
   }
}

$device_id = $best_device_id;

if (not defined %{$wurfl{'devices'}->{$device_id}}) {
    # Device not found
    exit;
}


# Build the list of fallback device ids

my @device_ids = ($device_id);
my $dev = $device_id;

while ($dev = $wurfl{'devices'}->{$dev}->{'attributes'}->{'fall_back'}
       and $dev ne 'root') {
   push @device_ids, $dev;
}


# Build a hash of the capabilities of the device using
# the fallback list, starting with the most generic

my %caps = ();

while ($dev = pop(@device_ids)) {

    my $dev_caps = $wurfl{'devices'}->{$dev}->{'capabilities'};

    foreach my $group ( keys (%{$dev_caps})) {

       foreach my $cap ( keys (%{${dev_caps}->{$group}})) {

          $caps{$group}->{$cap} = ${dev_caps}->{$group}->{$cap};
       }
    }
}


# Return the information as WML

print qq[Content-type: text/vnd.wap.wml\n\n];

print qq[<?xml version="1.0"?>\n];
print qq[<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" 
         "http://www.wapforum.org/DTD/wml_1.1.xml">\n];

print qq[<wml>\n];
print qq[<card id="main" title="Wurfl test">\n];
print qq[<p>WURFL Test - WML<br/>\n];

print qq[<b>Device ID</b> $device_id <br/>];
print qq[<b>User Agent</b> $ua <br/>];

print qq[<b>Rows</b>] . $caps{'display'}->{'rows'} . qq[<br/>];
print qq[<b>Cols</b>] . $caps{'display'}->{'columns'} . qq[<br/>];

my $height = $caps{'display'}->{'resolution_height'};
my $width  = $caps{'display'}->{'resolution_width'};

print qq[<b>Display Height</b>] . $height . qq[<br/>];
print qq[<b>Display Width</b>]  . $width . qq[<br/>];

print qq[<br/>\n];
print qq[<img src="/mobile/ora/line.wbmp" alt="line" 
         width="$width" height="10"/>];

print qq[</p></card></wml>\n];
exit;

This script finds the best match in the WURFL to your User Agent and then constructs the "fallback" list of more generic feature profiles. It then builds a hash of the specific capabilities of your phone using those profiles. To keep the example short, I only return the information in WML and limit the data to the screen size in pixels and characters. It uses the screen width to scale an image of a line so as to span the entire screen of your phone.

In principle, the WURFL is a great idea, but the reality leaves something to be desired. For example, my Nokia 3650 has a physical screen width of 176 pixels (and the WURFL correctly tells me this), but in reality, the browser can only access the center 171 pixels. It also tells me, incorrectly, that the access-key functions don't work. The WURFL represents a step forward; just don't rely too heavily on the more detailed information it returns.

If you only have access to a single phone but want to experiment with the WURFL, then you can use the simulators. Both applications let you specify the user agent they pretend to be. They don't take on the true feature set of that agent, in terms of screen size, etc., but they can be invaluable for testing your server-side applications.

You might think that the wireless industry would have set up something like this themselves, and indeed they have, in the form of the User Agent Profile (UAProf). This is one of the detailed and, in my personal opinion, horribly convoluted and acronym-ridden specifications that are managed by the Open Mobile Alliance (OMA). The WURFL folks include a link to an OMA white paper on the UAProf but, unfortunately, "Open" is a relative term, and this document is only accessible to OMA members. You can see what the UAProf file for the Openwave simulator looks like at this URL: devgate2.phone.com/uaprof/OPWVSDK62.xml.

Final Thoughts

The audience for the mobile Internet is growing rapidly. New phones have the capability to display rich, interesting, and attractive content. But the majority of the content that's available today ignores those features completely.

The diversity and rapid evolution of phone hardware is the source of the problem. In order to reach the widest audience, most sites have opted to support the lowest common denominator with web pages that use only basic text. Unless we overcome this limitation and deliver richer content, then the mobile Internet will not live up to its potential. Content that is tailored to different classes of browser is one way to move the field forward. Hopefully, the examples in this article will spark your interest in this area and help you get started developing your own pages.

Links

Robert Jones runs Craic Computing, a small bioinformatics company in Seattle that provides advanced software and data analysis services to the biotechnology industry. He was a bench molecular biologist for many years before programming got the better of him.


Return to the Wireless DevCenter