Tuesday, April 3, 2012

Until recently, building a web application with Oracle Application Express usually meant to build a desktop browser application. But if you look at the growing number of mobile devices, this will change very soon, if not already has for some of you. Being able to develop applications, that can be accessed by tablets or smart phones offers lots of new possibilities. But it also comes with some challenges. Mobile devices are different. Interaction by touch screen, screen size and (non-) support of certain common web functionality (flash, for example), just to mention a few.

Oracles announcement to integrate the jQuery mobile framework into APEX 4.2 will help us to deal with many of the challenges, developing for multiple devices will bring. Until now, one of the biggest challenges is, to determine the actual client your application is accessed on. Is it a desktop browser, a tablet or a smart phone? In this post I want to offer a solution that will provide an answer to this question, and can be used in APEX.

When building a web application, as a developer, you want to be able anticipate on how your application is being accessed. You might want to redirect the user to a different page or entirely different application. Or you might want to hide (i.e. not render) or show certain portions of a page. To be able to do so, you need to know the type of client used, and, ideally, be able to use this information in (PL/SQL) conditions.

Getting the info you need to decide

Every page request comes with a HTTP header, containing some generic information about the browser client it has been issued from: The HTTP_USER_AGENT string. This string holds information about browser, platform and version. The string itself can easily be accessed in PL/SQL by using the OWA_UTIL package function call:

l_user_agent := owa_util.get_cgi_env ('HTTP_USER_AGENT');

Once you've got the user agent string, the hard work starts. There are all kind of values you can get returned to you in the user agent string. It can be messy - VERY messy. Sometimes browser even lie about who they are, and the format is not standardized.

There are many approaches trying to find a way through this mess, and you can find a few articles on this at the bottom of this post. Some use databases with almost all possible user agent string stored, others try to decipher the string programmatically. Most of the code is available in Java, PHP or .net. I didn't find any appropriate code for PL/SQL. So I had to write my own or port some code I can understand.

Categorizr

What I wanted to achieve, was to be able to categorize the client device rendering the page in my application. I found some PHP code doing just that: Categorizr. The solution has some advantages:

It is lightweight and has not too many lines of code, which makes it reasonably easy to maintain it. With the growing number of mobile devices, I will have to maintain the algorithm. The approach chosen by the developer assumes the device to be a mobile device and then checks for other categories. By assuming devices are mobile from the beginning, Categorizr aims to be more future friendly. When new phones come out, you don’t need to worry if their new user agent is in your device detection script since devices are assumed mobile from the start.

The algorithm uses Regular Expressions, which are supported by PL/SQL. This minimizes the changes I have to apply to the code (Year, I know: I’m lazy).

Due to the minimal codebase and not querying large databases or accessing a web service, it’s fast.

The PLSQL package (specification) I have written offers these functions that you can use in your (APEX) PL/SQL code:

The functions can easily be used in APEX region conditions or any other PL/SQL code. Install the package in your workspace’s schema or in a separate schema with execute granted to public and a public synonym on it.

I tested the package against a list of. 11,000 common user agent strings. The algorithm is not failsafe, but reasonably accurate. Of course I cannot test every client possible. Try the demo page I prepared and drop me an email if you believe the outcome of the package is not correct.