Native apps, Mobile apps, or just apps. We call them different things and we use them all the time. From a business perspective, apps complement mobile and desktop sites. They are natural extension of an online strategy. Because of this, its important to take the necessary steps to make sure the native apps, and their versions, are identifiable. This is critical both from an analytics perspective as well as from a devops or support perspective. Native apps have much in common with the web. Apps often use the same online resources as the web site like RESTful APIs, images or videos. Because these resources are shared, it is very important to correctly form User-Agents for mobile apps to identify who is using the resources. Is the user on the Android app or iOS app? Which version of the app? Which OS version? And so on. Show There are two kinds of mobile apps: 1) fully native apps, and 2) webview-based hybrid apps. In this post, we will focus on fully native apps where HTTP requests are sent by the native code. If you are interested in webview-based hybrid apps where a browser window is wrapped in a native shell, then check out this other post on User-Agent strings for hybrid webview apps. The User-AgentThere is already an industry standard for device identification that apps can also use. Its the User-Agent string. The User-Agent string is a field in the HTTP header that can identify the app that is making the request. In a web browsing experience, the User-Agent is set by the browser (which is also an app). Now, instead of a browser, our native app will be making the HTTP request. When were developing a native app for a mobile phone, we need to take steps to ensure our User-Agent includes information that is meaningful. Otherwise the app will get the default values, which is not very helpful in any context. How to form a meaningful User-Agents for mobile appsThe specification is clear:
The specification goes in more detail and concludes that User-Agents should consist of one or more product identifiers and optional versions.By convention, the product identifiers are listed in decreasing order of their significance for identifying the User-Agent software. Lets dive right in and see how to compose meaningful User-Agent strings for native apps in the different platforms: Native Android AppBased on the specification above, the template we want for the User-Agent of our app is: <AppName>/<version> Dalvik/<version> (Linux; U; Android <android version>; <device ID> Build/<buildtag>)For example: The significant part here is Myapp/1 which identifies the native app and the version of the app. This is the most significant. The rest of the string identifies the underlying software. In Android, it is relatively easy to compose a custom User-Agent string. Here is some sample code: URLConnection cn = new URL("http://....").openConnection(); cn.setRequestProperty("User-agent", Myapp/1 + System.getProperty("http.agent")); cn.connect();If youre using the popular Picassolibrary, then the composition is similar. However, the actual request is made in a slightly different way. Have a look a thisexample app built with Picasso on Github. Native iOS AppUser-Agents for iOS are slightly more complex due to the fact that we have to account for both Objective-C and Swift. A default User-Agent in iOS may look something like this: MyApp/1 CFNetwork/808.3 Darwin/16.3.0In iOS a component called CFNetwork handles the network communications. Also involved is the UNIX version iOS is built on: Darwin. Both of these are mentioned in the default User-Agent. In addition there may be a custom app identifier added.So not very meaningful. In order to construct a more meaningful User-Agent we need more information added to it, like so: For example: MyApp/1 iPhone5,2 iOS/10_1 CFNetwork/808.3 Darwin/16.3.0The main challenge in constructing the User-Agent in iOS is to collect all the parameters needed. For example, it is not obvious how to find the CFNetwork- and Darwin values. Weve wrote an example app in Objective-C and Swiftwith the functionality needed to gather all bits that go into the User-Agent string. Feel free to use it. Once the bits are collected, just call the function to compose the User-Agent before you make a request: Objective-CNSString* userAgent = getUAString(); NSURL* url = [NSURL URLWithString:@""]; NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url]; [request setValue:userAgent forHTTPHeaderField:@"User-Agent"];For full code of the getUAString() function, see Github. Swiftlet userAgent = UAString() if let url = NSURL(string: "") { let request = NSMutableURLRequest(url: url as URL) request.setValue(userAgent, forHTTPHeaderField: "User-Agent") //... }For full code of the getUAString() function, see Github. Windows PhoneEven if not as popular as Android and iOS, Windows Phone is also worth mentioning. The semantic of the User-Agent is similar: For example: MyApp/1 Windows Phone/10.0 Microsoft; Lumia 550You can get the device brand name and model name from the EasClientDeviceInformation class with the SystemManufacturer and SystemProductName properties. The OS version can be extracted from DeviceFamilyVersion property in the AnalyticsVersionInfo class. Final ThoughtsEven if your favorite library or framework is not covered in this post, these examples should be generic enough to be transferred to any framework. Its worth spending the additional few minutes of development to make sure the User-Agent of your app is meaningful and conforms to specification. Your analytics, devops, and debugging will all benefit. And likewise, you can leverage this device detection to target specific devices, apps, or app versions on specific platforms with messages, ads or content. This article covered User-Agents in fully native apps. If your app is a webview based app (or hybrid app), then read Correctly Form User-Agents for Webview Apps |