SolutionsTools & SDKSupportForums Register
Quick Links
 
February 2003
 
 
Jack's Hack for the month of February, 2003:

Device Capabilities and UAProf

WAP 1.2.1 (June 2000 release) introduced a new way to determine handset capabilities.  The standard of User Agent Profile (UAProf) has been around for a while, yet few have implemented systems that take advantage the facilities it provides. In this article, I will introduce a software component called DELI and how to use it to extract information from UAProf.


UAProf
In a nutshell, UAProf is a RDF (resource description framework) document consisting of components and each component has a number of attributes. ( For more on what exactly an RDF is check out the RDF Primer from the W3C at http://www.w3.org/TR/rdf-primer/). 

Each attribute has a distinct name and has an associated collection type and attribute type.  UAProf also has a vocabulary system within components to enable common attribute names throughout the UAProf implementations for WAP 1.2.1 (or above) devices.  The UAProf of a device can be verifies against the schemas provided by WAP Forum. Three of such schemas exist and the latest version is available here (http://www.wapforum.org/profiles/UAPROF/ccppschema-20020710).
Please note also the UAProf component can be extended for other device capabilities. MmsCharacteristics is a good example of schema that is not in WAP Forum's UAProf list. The following are some URLs that point to the location of real UAProf documents:

Siemens S55: http://communication-market.siemens.de/UAProf/S55_00.xml
Sharp GX-10: http://sharp-mobile.com/UAprof/GX10.xml
LG-LX5350: http://device.sprintpcs.com/LG/5350/LX5350_11.rdf
SonyEricsson T300: http://wap.sonyericssonmobile.com/UAprof/T300R101.xml

At the end of the day, these RDF documents are simply XML. You can, if you choose, use your favorite tools and environments to parse the XML and get at the data you need. However, rather than reinvent the wheel here and build our own XML parser for UAProf from scratch, we will instead turn to the Open Source community and leverage

DELI
DELI it is an open source project available from http://delicon.sourceforge.net/ that that allows Java servlets to resolve HTTP requests containing delivery context information from CC/PP or UAProf capable devices and query the resolved profile. It also provides support for legacy devices so that the proprietary delivery context descriptions currently used by applications can be replaced by standardised CC/PP descriptions. Once DELI is enabled in your application. It will automatically determine the best set of UAProf attributes to use and make them available to your system.  If DELI cannot find the HTTP header "x-wap-profile" or "profile" then it will look up its legacy database using the user agent string sent by the request.  This database basically is a number of known UAProf documents stored as individual files (which makes updating easy).

The following example shows how to make use the attribute "ScreenSize" in order to select a picture that is suitable for the device's screen width.  The example uses images with dimension of 120x120, 101x101, 144x144 and 80x80 (default) and makes use of DELI version 0.7.0.  In order to avoid the need to recompile DELI, the the example servlet has been included to be used in the ccpp folder as a bit of a hack, but works fine with Apache Tomcat.

In examining the doGet method of the code, the work of obtaining and parsing the UAProf is all done in one simple call to the constructor of the Profile class (part of the Deli Package).
         Profile deviceProfile = new Profile(req);
The constructor simply takes the HTTP request, parses it, matches it against the local library of RDFs or fetched the RDF referenced in the UAProf HTTP Header if not stored locally. Once we have the profile loaded we check the BrowserName to determine if we really have a wireless device accessing the site or something like InternetExplorer or Mozilla with a call to
         ProfileAttribute bn= deviceProfile.getAttribute("BrowserName")
Once we have decided that the browser is a wireless deivce we then use the created Profile object in the selectPict method where we call
         ProfileAttribute ss = theProfile.getAttribute("ScreenSize");

The ProfileAttribute (another Deli class) is a vector created with the value of the ScreenSize attribute from the RDF file, which in its raw form looks like:
         <prf:ScreenSize>120x160</prf:ScreenSize>

Based on this vector, we can select the appropriate image to deliver to the handset, and use this image in our WML deck. Clearly, this is a very simple use of UAProf, and only represents the surface of what can be done with the information available. The sample code below is available for download as a zip file here, and also can be viewed in its deployed form at http://demo.openwave.com/uaprof


	  
import java.io.*;
import java.util.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.hp.hpl.deli.*;

public class ScreenRes extends HttpServlet
{
	Workspace workspace;
    	protected ServletContext servletContext;

	public void init(ServletConfig config) throws ServletException
	{
		super.init(config);
		servletContext = config.getServletContext();
		try
		{
			Workspace.getInstance().configure(servletContext, "config/deliConfig.xml");
		}
		catch (Exception e) 
		{		
            		System.out.println(e.toString());
        	}
	}

	public void printWML(Profile theProfile, PrintWriter out)
	{
        StringWriter outstr = new StringWriter();
		String inlineImg=selectPict(theProfile);

		ProfileAttribute ssAttr = theProfile.getAttribute("ScreenSize");		
		String screenSize = ssAttr.getValue().toString();
		String ss= screenSize.substring(1,screenSize.length()-1);

		ProfileAttribute bnAttr = theProfile.getAttribute("BrowserName");		
		String browserName = bnAttr.getValue().toString();
		String bn= browserName.substring(1,browserName.length()-1);
		
		outstr.write("<?xml version=\"1.0\"?>\n");
		outstr.write("<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">\n");
		outstr.write("<wml>\n");
		outstr.write("<card id=\"pict\">\n");
		outstr.write("<p>"+"<img src=/ccpp/\"" +inlineImg +"\" alt=\"wait...\"/></p>");
		
		outstr.write("<p>The browser name is "+bn +"</p>"+"\n");
		outstr.write("<p>Screen Size of this device is "+ss +"</p>"+"\n");

		outstr.write("</card>\n");
		outstr.write("</wml>\n");
                String str = outstr.getBuffer().toString();
                out.print(str);
	}
	
	public void printHTML(Profile theProfile, PrintWriter out)
	{
		String inlineImg=selectPict(theProfile);
		ProfileAttribute bnAttr = theProfile.getAttribute("BrowserName");		
		String browserName = bnAttr.getValue().toString();
		String bn= browserName.substring(1,browserName.length()-1);

		out.println("<HTML>\n<HEAD><TITLE>UAProf Example</TITLE></HEAD>\n");
		out.println("<BODY><H1>UAProf Example</H1>");
		out.println("<P> The Browser Name is:"+ bn);
		out.println("<P><img src=/ccpp/\"" +inlineImg +"\" alt=\"wait...\"/></P>");
		out.println();

		out.println("</BODY></HTML>");
	}
	

	private String selectPict(Profile theProfile)
	{
		String imageName="image/pictDefault.jpg";
		ProfileAttribute ss = theProfile.getAttribute("ScreenSize");
		if (ss!=null)		
		{		
			String ssAttrValue = ss.getValue().toString();
			String ScreenSize= ssAttrValue.substring(1,ssAttrValue.length()-1);
			
			if (ScreenSize.startsWith("120"))
			{
				imageName="image/pict120.jpg";
			}else if (ScreenSize.startsWith("101"))
			{
				imageName="image/pict101.jpg";
			
			}else if (ScreenSize.startsWith("144"))
			{
				imageName="image/pict144.jpg";
			}
		}
		return imageName;
	}

	public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
	{
		PrintWriter out = res.getWriter();
		Profile deviceProfile = new Profile(req);
		ProfileAttribute bn= deviceProfile.getAttribute("BrowserName");
		if (bn!=null)
		{
			String bnValue=bn.getValue().toString();
			String BrowserName= bnValue.substring(1,bnValue.length()-1);
			if (BrowserName.equals("Microsoft")||BrowserName.equals("Mozilla"))
			{
				res.setContentType("text/html");
				printHTML(deviceProfile, out);
			}else
			{
				res.setContentType("text/vnd.wap.wml");
				printWML(deviceProfile, out);
			}
		}



		res = UAProfCreateHttpResponse.addWarningHeader(res, UAProfCreateHttpResponse.CONTENT_GENERATION_APPLIED);
	}
}

Installing the example:
Download and install DELI 0.7.0. (do not use 0.8.0)
Copy the image folder to the ccpp folder of DELI
Add a folder called "classes" in the WEB-INF folder.
Copy the ScreenRes.class file there.
Add a servlet mapping to the web.xml file (example included).

It is not very exciting to access this servlet with a standard HTML browser such as Netscape or IE,  but you should use the 6.2 SDK, or any device that actually supports UAProf. 


To use DELI in your servlets, you will need to initialise in the HttpServlet's init method (full details in DELI user doc). The UAProf attribute is stored in standard Java vectors but you can also access the value directly.

For example:
System.out.println(myProfile.getAttribute("BrowserName").toString());


Download the source code and image resources used in this technote.

 
Copyright © 2000-2008 Openwave Systems Inc.    About Us  |  Openwave  |  Terms & Conditions  |  Privacy Policy  |  Update Profile