Thursday 6 September 2012

Programmatically get User-Agent String - Android and iOS

This post details how to obtain a device's default User-Agent string for Android and iOS development.

Getting programmatic access to a device's User-Agent string isn't always easy; in fact, it seems outright difficult in a lot of cases. This post will detail how you should obtain such information when developing for Android and iOS. Note, the information on the Android section requires Android 2.1 and up (more details below).

What is a User-Agent string?

User-Agent strings provide details about the device that is making a request to a server. Basically, it is a way of helping the server identify what kind of device is asking for data.

Here is an example, of an iPhone running iOS 6 (Beta):
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.2

What does 'default User-Agent' really mean?

That's a good question. By my definition, the default User-Agent basically refers to the User-Agent string that the device's default browser would use when requesting websites. Each browser of course, will likely send a modified User-Agent string.

Why do I need to care?

User-Agent strings are often an essential piece of information when submitting data to a server; the server might require it to cater device-specific optimised data, the server might just want to log it, or it might well just refuse to release data to a request that hasn't provided it.

In the simplest of examples, when using a browser to access a website, the server might look at your User-Agent string and decide whether to serve you the "desktop" page, or the "mobile" page, based on what data is provided in your User-Agent string.

Providing a hardcoded User-Agent string in your app might seem tempting, but this can really result in a bad user experience for users, depending on how/if the server uses that information. As every good developer knows; it is all about the user experience! Thankfully, you don't have to bend over backwards to find the User-Agent string.

Android

Since Android 2.1, a system property has been included which contains the default User-Agent string. This is really great as it allows quick retrieval of the UA string without the overhead of creating a Web View, simply to extract the string.

String userAgent = System.getProperty("http.agent");

iOS

In order to obtain the User-Agent on iOS, you need to instantiate a UIWebView, and execute a javascript command to obtain the UA string.

UIWebView *webView = [[UIWebView alloc]initWithFrame:CGRectZero]; 
NSString *uaString = [webView stringByEvaluatingJavaScriptFromString:"@navigator.userAgent"];


A good tip here is to execute the above once, and assign it to a variable - the User-Agent string is not going to change during the execution of your app, and it is more efficient than performing an instantiation of a UIWebView often, just to get the same string.

2 comments:

  1. "Providing a hardcoded User-Agent string in your app might seem tempting, but this can really result in a bad user experience for users"
    100% Correct.

    Thousands of websites will block or at least challenge unrecognized user-agent, for fear of malicious bots (spammers, scanners, scrapers and etc) To consolidate bot information, we've recently launched a community-sourced bot directory (Botopedia.org) to be used freely by all members of Internet community.

    ReplyDelete
  2. System.getProperty("http.agent") does not return the same user agent as the WebView object. I have tested this on a Samsung Galaxy SII with Android 4.1.2:

    System.getProperty("http.agent") = "Dalvik/1.6.0 (Linux; U; Android 4.1.2; GT-I9100 Build/JZO54K)"

    new WebView(getApplicationContext()).getSettings().getUserAgentString() = "Mozilla/5.0 (Linux; U; Android 4.1.2; es-es; GT-I9100 Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"

    As you can see they are quite different. In fact I you set the first one to a WebView the pages are rendered quite different in mobile aware sites, like Google for example.

    I personally use the user agent string to load pages in the background with an async task so I need to use exactly the same agent as the webview to be sure to get the perfect page.

    This tip may have worked in the past, I suppose.

    ReplyDelete