Wednesday, 16 February 2011

Request.Browser.IsMobileDevice

It's known that the .Net framework's "Request.Browser.IsMobileDevice" is not entirely reliable in all cases as evidenced by the fact that our MVC2 site wasn't correctly detecting Android as a mobile, and as evidenced by some hits you can see in this search:

http://www.bing.com/search?q=request.browser.ismobiledevice&src=IE-SearchBox&FORM=IE8SRC

If we really want reliable mobile detection we need to incorporate the WURFL database (a giant XML file of every mobile device - see http://wurfl.sourceforge.net/ ) and from what I’ve seen, the preferred implementation of this for .Net appears to be “51degrees.mobi” …

http://51degrees.codeplex.com/

On the MVC2 project I’ve been working on recently, I was using 51degrees.mobi in development; it seemed very effective, and you can do incredibly granular detection with it, but was a bit heavyweight for my particular project, the requirements of which were (in the case of mobile detection) simply to detect whether it was a mobile device, and display a different view if so.  Our list of supported mobiles was quite small, and the only one that weren’t being detected correctly by the “Request.Browser.IsMobileDevice” flag were Android phones.

So I was just using “Request.Browser.IsMobileDevice” which was working fine until I heard about the Android issue. 

Anyway, the following is a bit of a hack, but I just handled that case in a specific way… I looked at the "user agent" value that comes across in the request.  I also looked (physically, not in code) at the WURFL XML file that comes with 51degress.mobi, for a generic Android phone, because I assume that’s how WURFL is doing its detection anyway.  In the WURFL database, the user agent string for a generic Android is:

Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522+ (KHTML, like Gecko) Safari/419.3

So it seemed safe to assume “Android” would exist in the user agent string; so now I'm just looking for the word "android" (converted to lower case in code) in the user agent string, and if it's found, I tell the app to behave just like it does with other mobile devices.

// special case; Android phones were not being detected as mobiles by Request.Browser.IsMobile;

// this is a quick & dirty solution.  The preferred solution would be to integrate the WURFL database

// and the DLLs from http://51degrees.codeplex.com/ but it's too heavyweight of a solution for this

 

var useragent = Request.UserAgent;

var isAndroid = false;

 

if (useragent != null)

{

    if (useragent.ToLower().Contains(Constants.MobileDevices.Android))

    {

        isAndroid = true;

    }           

}

 

if (Request.Browser.IsMobileDevice || isAndroid)

{

    // … do something specific for mobiles, particularly, display the mobile view

I tested it with a "user agent switcher" add-on for Firefox that I found here:

http://chrispederick.com/work/user-agent-switcher/features/

and it correctly went to the mobile version of the site as if I were running on an Android.

The add-on might not work in every case, but in this situation it did the job, and is bit easier than using a mobile emulator.

Anyway again, a bit of a hack, but turned out to be an effective quick and dirty solution to this particular problem.

8 comments:

  1. Nice idea but how would you differentiate between an Android mobile and an Android tablet?

    ReplyDelete
  2. Hi Mitch, thanks for your comment. On that project, the requirements weren't specific to individual devices; the front-end code was written such that there was a desktop view, and a mobile view. So in that case we didn't need that much granularity.

    But from what I saw of it, the WURFL database appeared to have entries for most devices on the market so I would think its data can differentiate between an Android mobile and tablet. I'd suggest this: http://51degrees.codeplex.com/ (or some similar API to the WURFL database). Regards, dB

    ReplyDelete
  3. Ah, I re-read my code example further and see your point. I'd stick with my suggestion. If you need more granularity than my code example provides I think 51 degrees.mobi / the WURFL database could do the trick with a bit more coding.

    ReplyDelete
  4. Thanks for the post. Your post just solved my issue :-)

    ReplyDelete
  5. Hi Mohammad, glad my post was useful to you!

    ReplyDelete
  6. Thank you .... One question, we have asp.net 2.0 web app, we need to add mobile version and redirect mobile user to it, now in asp.net web we already have where should this code go ...? In each page load ? There lot of pages or In global.asax ?if global.asax, which event better fits ?

    ReplyDelete
  7. There are a few options and techniques; here are some ideas that you could adapt to your situation (the second one is ASP.NET 3.5, not sure if it would work in 2.0 but it might). Application_BeginRequest in global.asax seems a logical choice. Putting it in each Page_Load seems a recipe for a maintenance headache. It's been awhile since I've worked with ASP.NET 2.0 but putting some code in a master page load might be an option (as in the 4th URL below). You might try posting your question on stackoverflow if these ideas don't help.

    http://stackoverflow.com/questions/4755407/how-to-make-301-permanent-redirect-in-asp-net

    http://www.codeproject.com/Articles/110595/Handling-301-Redirects-in-ASP-NET-3-5

    http://www.developer.com/net/asp/article.php/3299641/ServerTransfer-Vs-ResponseRedirect.htm

    http://stackoverflow.com/questions/10667010/redirect-in-master-page-before-content-page-load

    ReplyDelete