class DeviceAtlas

Copyright
Author

Used to load the recognition tree and perform lookups of all properties, or get individual properties. Typical usage is as follows:

deviceAtlas = DeviceAtlas.new
path = File.join(File.dirname(__FILE__), '..', 'data_file/sample.json')
tree = deviceAtlas.getTreeFromFile(path)
properties = deviceAtlas.getProperties(tree, "Nokia6680...")
property = deviceAtlas.getProperty(tree, "Nokia6680...", "displayWidth")

Note that you should normally use the user-agent that was received in the device's HTTP request. In a Rails environment, you would do this as follows:

userAgent = request.env['HTTP_USER_AGENT']
displayWidth = deviceAtlas.getPropertyAsInteger(tree, userAgent, "displayWidth")

Third-party Browsers:

In some contexts, the user-agent you want to recognise may have been provided in a different header. Opera's mobile browser, for example, makes requests via an HTTP proxy, which rewrites the headers. in that case, the original device's user-agent is in the “X-OperaMini-Phone-UA” header, and the following code could be used:

operaHeader = "X-OperaMini-Phone-UA"
if request.headers.include?(operaHeader)
        userAgent = request.headers[operaHeader]
else
        userAgent = request.env['HTTP_USER_AGENT']
end
displayWidth = deviceAtlas.getPropertyAsInteger(tree, userAgent, "displayWidth")

See here for more information: deviceatlas.com/resources/side-loaded-browser-handling

Client side properties:

Client side properties can be collected and merged into the results by using the DeviceAtlas Javascript detection file. The results from the client side are sent to the server inside a cookie. The contents of this cookie can be passed to the DeviceAtlas getProperty and getProperties methods. The client side properties over-ride any data file properties and also serve as an input into additional logic to determine other properties such as the iPhone models that are otherwise not detectable. The following code shows how this can be done in Rails:

userAgent = request.env['HTTP_USER_AGENT']
cookieContents = request.cookies['DAPROPS']
properties = deviceAtlas.getPropertiesAsTyped(tree, userAgent, cookieContents)

Constants

API_ID

Public static constants.

PROPERTIES_WITHOUT_TYPE_TO_ID

Attributes

ID_TO_PROPERTY_WITHOUT_TYPE[R]

Public non-static constants.

ID_TO_VALUES[R]

Public non-static constants.

PROPERTIES_WITH_TYPE_TO_ID[R]

Public non-static constants.

Public Class Methods

new() click to toggle source
# File ../Src/deviceatlas.rb, line 104
def initialize
        
        # Set the public constants.
        @PROPERTIES_WITH_TYPE_TO_ID = 'pr' # e.g. bmobileDevice: 1
        @ID_TO_PROPERTY_WITHOUT_TYPE = 'pnr' # e.g. 1: mobileDevice
        
        # Set private constants.
        @AV_PROPS = 100 #chosen as an average num of properties returned
        @CLIENT_PROPS_HANDLER = '_cprops'
        @UA_PROPS_HANDLER = '_uaprops'
        @MAIN_TREE_BRANCH = 't'
        @REGEX = 'r'
        @COMPILED_REGEX = 'creg'
        
        # Initialize a private instance variable.
        @cachedTree = nil
        
end

Public Instance Methods

getApiRevision() click to toggle source

Return the revision number of this API.

# File ../Src/deviceatlas.rb, line 234
def getApiRevision()
        _getRevisionFromKeyword('$Rev: 28642 $')
end
getProperties(tree, userAgent, cookie = nil, typedValues = false, sought = nil, uaPropsNeeded = true) click to toggle source

Return a associative array of known properties merged with properties from the client side JavaScript. The client side JavaScript sets a cookie with collected properties. The contents of this cookie must be passed to this method for it to work. The client properties over-ride any properties discovered from the main JSON data file.

tree

Previously generated associative array tree.

userAgent

The device's User-Agent header string.

cookie

The contents of the cookie containing the client side properties.

typedValues

Whether values in the results are typed.

sought

A set of properties to return values for.

uaPropsNeeded

Whether the extra properties from the UA String are needed.

# File ../Src/deviceatlas.rb, line 269
def getProperties(tree, userAgent, cookie = nil, typedValues = false, sought = nil, uaPropsNeeded = true)

        if !cookie.nil?
                getPropertiesWithCookie(tree, userAgent, cookie, typedValues)
        else
                getPropertiesWithoutCookie(tree, userAgent, typedValues, sought, uaPropsNeeded)
        end
end
getPropertiesAsTyped(tree, userAgent, cookie = nil) click to toggle source

Return an associative array of known properties merged with properties from the client side JavaScript. The client side JavaScript sets a cookie with collected properties. The contents of this cookie must be passed to this method for it to work. The client properties over-ride any properties discovered from the main JSON data file.

tree

Previously generated associative array tree.

userAgent

The device's User-Agent header string.

cookie

The contents of the cookie containing the client side properties.

# File ../Src/deviceatlas.rb, line 404
def getPropertiesAsTyped(tree, userAgent, cookie = nil)
        getProperties(tree, userAgent, cookie, true, nil, true)
end
getProperty(tree, userAgent, property, cookie = nil, typedValue = false) click to toggle source

Return a value for the named property for this user agent.

tree

Previously generated associative array tree.

userAgent

The device's User-Agent header string.

property

The name of the property to return.

cookie

The contents of the cookie containing the client side properties.

typedValue

Whether value in the associative array are typed.

# File ../Src/deviceatlas.rb, line 416
def getProperty(tree, userAgent, property, cookie = nil, typedValue = false)
        if cookie.nil? || cookie.empty?
                return getPropertyWithoutCookie(tree, userAgent, property, typedValue)
        else
                return getPropertyWithCookie(tree, userAgent, property, cookie, typedValue)
        end
end
getPropertyAsBoolean(tree, userAgent, property, cookie = nil) click to toggle source

Strongly typed property accessor. Return a boolean property (or throws an exception if the property is actually of another type).

tree

Previously generated associative array tree.

userAgent

The device's User-Agent header string.

property

The name of the property to return.

# File ../Src/deviceatlas.rb, line 536
def getPropertyAsBoolean(tree, userAgent, property, cookie = nil)
        propertyTypeCheck(tree, property, "b", "boolean", cookie)
        getProperty(tree, userAgent, property, cookie, true)
end
getPropertyAsDate(tree, userAgent, property, cookie = nil) click to toggle source

Strongly typed property accessor. Returns a date property (or throws an exception if the property is actually of another type).

tree

Previously generated associative array tree.

userAgent

The device's User-Agent header string.

property

The name of the property to return.

# File ../Src/deviceatlas.rb, line 549
def getPropertyAsDate(tree, userAgent, property, cookie = nil)
        propertyTypeCheck(tree, property, "d", "date", cookie)
        getProperty(tree, userAgent, property, cookie, true)
end
getPropertyAsInteger(tree, userAgent, property, cookie = nil) click to toggle source

Strongly typed property accessor. Return an integer property (or throws an exception if the property is actually of another type).

tree

Previously generated associative array tree.

userAgent

The device's User-Agent header string.

property

The name of the property to return.

# File ../Src/deviceatlas.rb, line 562
def getPropertyAsInteger(tree, userAgent, property, cookie = nil)
        propertyTypeCheck(tree, property, "i", "integer", cookie)
        getProperty(tree, userAgent, property, cookie, true)
end
getPropertyAsString(tree, userAgent, property, cookie = nil) click to toggle source

Strongly typed property accessor. Return a string property (or throws an exception if the property is actually of another type).

tree

Previously generated associative array tree.

userAgent

The device's User-Agent header string.

property

The name of the property to return.

# File ../Src/deviceatlas.rb, line 575
def getPropertyAsString(tree, userAgent, property, cookie = nil)
        propertyTypeCheck(tree, property, "s", "string", cookie)
        getProperty(tree, userAgent, property, cookie, true)
end
getTreeFromFile(filename, reload = false, includeChangeableUserAgentProperties = true) click to toggle source

Return a tree from a JSON file. The loaded tree is stored in a static cache to avoid multiple reloads if this method is repeatedly called. To reload from the JSON file set “reload” to true.

Some properties cannot be known before runtime and can change from user-agent to user-agent. The most common of these are the OS Version and the Browser Version. This API is able to dynamically detect these changing properties but introduces a small overhead to do so. To disable returning these extra properties set “includeChangeableUserAgentProperties” to false.

filename

The location of the file to read in. Use an absolute path

name to be sure of success if the current working directory is not clear.

reload

Set true to reload regardless of static cache.

includeChangeableUserAgentProperties

Also detect changeable user-agent

properties.

# File ../Src/deviceatlas.rb, line 201
def getTreeFromFile(filename, reload = false, includeChangeableUserAgentProperties = true)             
        if reload || @cachedTree.nil?

                raise(JsonException, "Unable to find JSON file.") if !File.file?(filename)

                json = File.open(filename,"r").read                  
                @cachedTree = getTreeFromString(json, includeChangeableUserAgentProperties)
        end
        @cachedTree
end
getTreeFromString(json, includeChangeableUserAgentProperties = true) click to toggle source

Return a loaded JSON tree from a string of JSON data.

Some properties cannot be known before runtime and can change from user-agent to user-agent. The most common of these are the OS Version and the Browser Version. This API is able to dynamically detect these changing properties but introduces a small overhead to do so. To disable returning these extra properties set “includeChangeableUserAgentProperties” to false.

This method does not use the built in static cache.

json

The string of json data.

includeChangeableUserAgentProperties

Also detect changeable user-agent properties.

# File ../Src/deviceatlas.rb, line 136
def getTreeFromString(json, includeChangeableUserAgentProperties = true)

        tree = JSON::Parser.new(json, :max_nesting => false).parse
        raise(JsonException, "Unable to load Json data.") if (tree.nil? || !tree.kind_of?(Hash))
        raise(JsonException, "Bad data loaded into the tree.") unless tree.has_key?("$")
        raise(JsonException, "DeviceAtlas json file must be v0.7 or greater. Please download a more recent version.") if(tree["$"]["Ver"].to_f < 0.7)

        # Prepare three trees to speed up retrieval of properties.
        props = tree[PropsHandler::ID_TO_PROPERTIES_WITH_TYPE]

        pr = {}
        pn = {}
        newP = {}
        idToProp = {}

        props.each_with_index do |typeName, id|
                name = typeName[1..typeName.size]

                newP[id] = typeName # all keys in the JSON file are strings so make associative array with string keys...
                pr[typeName] = id
                pn[name] = id
                idToProp[id] = name
        end
        
        tree.delete(PropsHandler::ID_TO_PROPERTIES_WITH_TYPE)
        tree[PropsHandler::ID_TO_PROPERTIES_WITH_TYPE] = newP
        tree[@PROPERTIES_WITH_TYPE_TO_ID] = pr # propertytype+name => propertyid
        tree[@PROPERTIES_WITHOUT_TYPE_TO_ID] = pn # propertyname => propertyid
        tree[@ID_TO_PROPERTY_WITHOUT_TYPE] = idToProp # property names without the type char

        # Prepare the user-agent rules branch before we start recognition.
        # To maintain backwards compatibility - only do this if we have the ua rules branch
        if tree[UAProps::UA_RULES]
                unless includeChangeableUserAgentProperties
                        # remove the UAR branch to save some memory
                        tree.delete(UAProps::UA_RULES)
                else
                        tree[@UA_PROPS_HANDLER] = UAProps.new(tree) # stick in the tree so we can use it later
                end
        end

        if tree[ClientProps::CP_RULES]
                clientProps = ClientProps.new(tree)
                tree[@CLIENT_PROPS_HANDLER] = clientProps # stick in the tree so we can use it later
        end

        tree
end
getTreeGeneration(tree) click to toggle source

Get the generation date for this tree. Return the time/date the tree was generated.

# File ../Src/deviceatlas.rb, line 215
def getTreeGeneration(tree)
        tree['$']['Gen']
end
getTreeGenerationAsTimestamp(tree) click to toggle source

Get the generation date for this tree as a UNIX timestamp. Return the time/date the tree was generated.

# File ../Src/deviceatlas.rb, line 222
def getTreeGenerationAsTimestamp(tree)
        tree['$']['Utc']
end
getTreeRevision(tree) click to toggle source

Return the revision number of the tree.

# File ../Src/deviceatlas.rb, line 228
def getTreeRevision(tree)
        _getRevisionFromKeyword(tree['$']['Rev'])
end
listProperties(tree) click to toggle source

Return an associative array of all property names available for all user agents in this tree, with their data type names.

# File ../Src/deviceatlas.rb, line 247
def listProperties(tree)
        types = {"s" => "string", "b" =>"boolean", "i" =>"integer", "d" =>"date", "u" =>"unknown"}
        properties = {}
        tree[PropsHandler::ID_TO_PROPERTIES_WITH_TYPE].each do |id, property|
                properties[property[1..property.length]] = types[property[0]]
        end
        properties
end