Print

Creating Web Content for Mobile Phone Browsers, Part 2

by Robert Jones
02/20/2004

In part 1 of this series, I took you inside the WML and XHTML MP markup languages, highlighted the differences between them, and showed how to serve pages in these languages from an Apache web server. In this article, I want to show you how we deal with the diversity of phones out there, and how we can tailor our content to communicate effectively with these phones.

This diversity is the curse that afflicts most of the WAP sites in use today. Aiming for as large an audience as possible, sites are forced to use only the most basic features of WML, which is already one of the more basic markup languages. The resulting web pages are dull and completely ignore the capabilities of newer phones. But those new features, in particular the larger color screens, are exactly the reason people are buying new phones!

How do we resolve this? Even if we give up on older phones and just deliver XHTML MP, we still have to deal with a range of screen sizes and browser features. It's a mess. But with a little bit of extra work, there are several approaches that can move us forward.

Related Reading

HTML & XHTML: The Definitive Guide
By Chuck Musciano, Bill Kennedy

In any request for a page from a web server, there are two pieces of information we can use. The HTTP_ACCEPT header contains the MIME types that a browser can accept. This tells us the type of information that we can return. The HTTP_USER_AGENT header tells us the identity of the browser and, typically, the phone. That alone does not do us a lot of good, but with a database that maps identity to things like screen size, then we can infer how to best display our content.

Server Redirection

Our first approach will use the HTTP_ACCEPT header of a request to figure out if a browser is a mobile phone and whether it can handle XHTML MP or just WML. All of the action happens in the web server itself, so this is a great solution for static web pages.

It also addresses another problem, in that we want to avoid entering long URLs into a mobile browser at all costs. For most sites, the best solution would be for a user (mobile or not) to simply go to the home page. With server redirection, we can detect the type of browser and return the regular home page to desktop browsers, but redirect mobile browsers to a simpler page of contact information. With the Apache web server, we accomplish this using the URL rewriting capabilities of the mod_rewrite module. This is a superb toolkit for manipulating URLs, but it is complex, and so in this article we'll only present the minimum information needed for our present purpose.

Take a look at your Apache configuration file (/etc/httpd/conf/httpd.conf) and look for these two lines. They should both be there, but you might need to un-comment them. These load the rewrite functions into the Apache.

LoadModule rewrite_module	modules/mod_rewrite.so
AddModule mod_rewrite.c

Next, we need a Directory block that defines what happens when a specific page is requested. Set the directory path and filenames to those appropriate to your site and enter all the statements. Rewrite statements work by defining a set of conditions and a rule that is applied to files that match the conditions. The first "block" of conditions and rules that are matched to a browser request are used, and subsequent blocks are skipped.

<Directory "/var/www/craic_external/html/mobile/ora">

  # This enables rewriting in this directory

  RewriteEngine On

  # Catch XHTML MP browsers first and return XHTML MP content to them
 
  # Our conditions are that the browser must accept XHTML MP and WML
  # content. If we just use the xhtml+xml rule then we catch Mozilla 
  # browsers by mistake.
  # There is an implicit AND between the two conditions.

  RewriteCond %{HTTP_ACCEPT} application/xhtml\+xml
  RewriteCond %{HTTP_ACCEPT} text/vnd\.wap\.wml

  RewriteRule index.html$ index.xhtml [L]

  # This next block will catch browsers that only understand WML

  RewriteCond %{HTTP_ACCEPT} text/vnd\.wap\.wml

  RewriteRule index.html$ index.wml [L]

  # Browsers that match neither block, such as regular screen 
  # browsers, could be caught by a final rewrite rule placed here,
  # or we could leave it out and have nothing happen to the 
  # requested URL. This is the default.

</Directory>

If a browser passes the URL http://www.craic.com/mobile/ora, Apache will add "index.html" to it by default. If that request comes from a XHTML MP browser, then index.html will be rewritten to index.xhtml, and that file will be returned. If the browser can only handle WML, the request is rewritten to "index.wml," and if the browser is "conventional," then nothing happens and index.html is returned. This is the block that controls the directory on my web site that contains all of these examples. Access it from a mobile browser, and you get the WML or XHTML MP pages displayed. Use a desktop browser, and you will get links to all of the source code.

CGI Scripts

Server redirection is easy to set up and great for handling static web pages. But when you have dynamic content (from a Perl CGI script, for example), it makes more sense to have the script figure out what the browser can accept and switch accordingly. Here is a simple CGI script that echoes the variables passed in a request back to the browser in the form of a HTML, WML, or XHTML MP page, as appropriate.

#!/usr/bin/perl -w

# mime_types.cgi

# Return the list of MIME types that the browser can handle
# in the appropriate markup language - HTML, XHTML MP or WML

use CGI;
my $cgi = new CGI;

my %accept = ();
foreach my $type (split /\s*\,\s*/, lc $cgi->http('HTTP_ACCEPT')) {
    $type =~ s/\s+//g;
    $type =~ s/\;.*$//;
    $accept{$type} = 1;
}

my $language = 'html';
if(exists $accept{'text/vnd.wap.wml'}) {
    $language = 'wml';
    if(exists $accept{'application/xhtml+xml'}) {
	$language = 'xhtml_mp';
    }
}

if($language eq 'wml') {
    respond_wml();
} elsif($language eq 'xhtml_mp') {
    respond_xhtml_mp();
} else {
    respond_html();
}

exit;

#-------------------------------------------------------------

sub respond_html {

   print qq[Content-type: text/html\n\n];

   print qq[<html><head><title>Browser Info - HTML</title></head>\n];
   print qq[<body bgcolor="white">\n];
   print qq[Browser Information - HTML<br>\n];

   foreach my $type (sort keys %accept) {
      print qq[$type <br>\n];
   }

   print qq[</body></html>\n];
}

#-------------------------------------------------------------

sub respond_xhtml_mp {

   print qq[Content-type: application/xhtml+xml\n\n];

   print qq[<?xml version="1.0"?>\n];
   print qq[<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"\n];
   print qq["  http://www.wapforum.org/DTD/xhtml-mobile10.dtd">\n];

   print qq[<html xmlns="http://www.w3.org/1999/xhtml">\n];
   print qq[<head><title>XHTML MP</title></head>\n];
   print qq[<body bgcolor="white">\n];
   print qq[Output as XHTML MP<br/>\n];

   foreach my $type (sort keys %accept) {
      print qq[$type <br/>\n];
   }

   print qq[</body></html>\n];
}

#-------------------------------------------------------------

sub respond_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" ];
   print qq["http://www.wapforum.org/DTD/wml_1.1.xml">\n];

   print qq[<wml>\n];
   print qq[<card id="main" title="WML">\n];
   print qq[<p>Output as WML<br/>\n];

   foreach my $type (sort keys %accept) {
      print qq[$type <br/>\n];
   }

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

You can access this example at: www.craic.com/cgi-bin/mobile/ora/mime_types.cgi.

Choosing between WML and XHTML MP for the markup and then returning a page that makes modest use of the features of each language seems like it could be the right level of effort for most WAP developers. It allows any WAP user to access our content but lets us apply some of the richer design features in XHTML MP where appropriate.

But the approach still does not tell us anything about the device that is making the request. We can get the device's identity from the HTTP_USER_AGENT header, but we need to know what that phone/browser is capable of displaying before we can really tailor our content. We want information such as the screen size and depth, and the navigation keys that are available to us. What we need is a database of information about every phone on the market that we can interrogate and use to tailor our response to a specific device.

Pages: 1, 2

Next Pagearrow