/* ******************************************* // LICENSE INFORMATION // The code, "Detecting Smartphones Using PHP" // by Anthony Hand, is licensed under a Creative Commons // Attribution 3.0 United States License. // // Updated 01 March 2010 by Bryan J Swift // - Remove un-needed if statements instead just returning the boolean // inside the if clause // // Updated 14 December 2009 by A Hand // - Added the method for detecting BlackBerry Touch // devices like the Storm 1 and 2. // // Updated 5 December 2009 by A Hand // - Fixed the DetectPalmOS method. It should filter // out WebOS devices. // // Updated 8 November 2009 by A Hand // - Added the deviceWebOS variable. // - Added Palm's WebOS to the DetectPalmOS method. // - Created a new method to check for Palm's WebOS devices. // - Added Palm's WebOS to the DetectTierIphone method. // // Updated 4 April 2009 by A Hand // - Changed the name of the class from DetectSmartPhone to UAgentInfo. // New name is more consistent with PHP and JavaScript classes. // - Added a method to detect Opera Mobile and Mini. Opera Mobile is new. // - Updated the algorithm for detecting a Sony Mylo. // - Added Android to the DetectTierIphone method. // - Updated comments for Detect Tier methods. // // Updated 22 January 2009 // - Ported to Java from the PHP code by // Satish Kumar Nookala, javasatish@yahoo.com // // Anthony Hand, ahand@hand-interactive.com // Web: www.hand-interactive.com // // License info: http://creativecommons.org/licenses/by/3.0/us/ // // This code is provided AS IS with no expressed or implied warranty. // You have the right to use this code or any portion of it // so long as you provide credit toward myself as the original author. // // ******************************************* */ package com.handinteractive.mobile; import javax.servlet.http.HttpServletRequest; /** * The DetectSmartPhone class encapsulates information about * a browser's connection to your web site. * You can use it to find out whether the browser asking for * your site's content is probably running on a mobile device. * The methods were written so you can be as granular as you want. * For example, enquiring whether it's as specific as an iPod Touch or * as general as a smartphone class device. * The object's methods return true, or false. */ public class UAgentInfo { // User-Agent and Accept HTTP request headers private String userAgent = ""; private String httpAccept = ""; // Initialize some initial smartphone string variables. public static final String engineWebKit = "webkit"; public static final String deviceAndroid = "android"; public static final String deviceIphone = "iphone"; public static final String deviceIpod = "ipod"; public static final String deviceSymbian = "symbian"; public static final String deviceS60 = "series60"; public static final String deviceS70 = "series70"; public static final String deviceS80 = "series80"; public static final String deviceS90 = "series90"; public static final String deviceWinMob = "windows ce"; public static final String deviceWindows = "windows"; public static final String deviceIeMob = "iemobile"; public static final String enginePie = "wm5 pie"; //An old Windows Mobile public static final String deviceBB = "blackberry"; public static final String vndRIM = "vnd.rim"; //Detectable when BB devices emulate IE or Firefox public static final String deviceBBStorm = "blackberry95"; //Storm 1 and 2 public static final String devicePalm = "palm"; public static final String deviceWebOS = "webos"; //For Palm's new WebOS devices public static final String engineBlazer = "blazer"; //Old Palm public static final String engineXiino = "xiino"; //Another old Palm //Initialize variables for mobile-specific content. public static final String vndwap = "vnd.wap"; public static final String wml = "wml"; //Initialize variables for other random devices and mobile browsers. public static final String deviceBrew = "brew"; public static final String deviceDanger = "danger"; public static final String deviceHiptop = "hiptop"; public static final String devicePlaystation = "playstation"; public static final String deviceNintendoDs = "nitro"; public static final String deviceNintendo = "nintendo"; public static final String deviceWii = "wii"; public static final String deviceXbox = "xbox"; public static final String deviceArchos = "archos"; public static final String engineOpera = "opera"; //Popular browser public static final String engineNetfront = "netfront"; //Common embedded OS browser public static final String engineUpBrowser = "up.browser"; //common on some phones public static final String engineOpenWeb = "openweb"; //Transcoding by OpenWave server public static final String deviceMidp = "midp"; //a mobile Java technology public static final String uplink = "up.link"; public static final String devicePda = "pda"; //some devices report themselves as PDAs public static final String mini = "mini"; //Some mobile browsers put "mini" in their names. public static final String mobile = "mobile"; //Some mobile browsers put "mobile" in their user agent strings. public static final String mobi = "mobi"; //Some mobile browsers put "mobi" in their user agent strings. //Use Maemo, Tablet, and Linux to test for Nokia"s Internet Tablets. public static final String maemo = "maemo"; public static final String maemoTablet = "tablet"; public static final String linux = "linux"; public static final String qtembedded = "qt embedded"; //for Sony Mylo public static final String mylocom2 = "com2"; //for Sony Mylo also //In some UserAgents, the only clue is the manufacturer. public static final String manuSonyEricsson = "sonyericsson"; public static final String manuericsson = "ericsson"; public static final String manuSamsung1 = "sec-sgh"; public static final String manuSony = "sony"; //In some UserAgents, the only clue is the operator. public static final String svcDocomo = "docomo"; public static final String svcKddi = "kddi"; public static final String svcVodafone = "vodafone"; // Standard desktop browser detection strings public static final String msie = "msie"; public static final String msie60 = "msie 6.0"; public static final String msie61 = "msie 6.1"; public static final String msie7 = "msie 7.0"; public static final String msie8 = "msie 8.0"; public static final String msie9 = "msie 9.0"; public static final String firefox = "firefox"; public static final String safari = "apple"; public static final String chrome = "chrome"; public static final String opera = "presto"; // OS Detection public static final String windows = "windows"; /** * Initialize the userAgent and httpAccept variables * * @param userAgent the User-Agent header * @param httpAccept the Accept header */ public UAgentInfo(String userAgent, String httpAccept) { if (userAgent != null) { this.userAgent = userAgent.toLowerCase(); } if (httpAccept != null) { this.httpAccept = httpAccept.toLowerCase(); } } /** * Initialize the userAgent and httpAccept variables by getting the headers * from the HttpServletRequest * * @param request the HttpServletRequest to get the header information from */ public UAgentInfo(HttpServletRequest request) { this(request.getHeader("User-Agent"),request.getHeader("Accept")); } /** * Return the lower case HTTP_USER_AGENT */ public String getUserAgent() { return userAgent; } /** * Return the lower case HTTP_ACCEPT */ public String getHttpAccept() { return httpAccept; } /** * Detects if the current device is an iPhone. */ public boolean detectIphone() { // The iPod touch says it's an iPhone! So let's disambiguate. return userAgent.indexOf(deviceIphone) != -1 && !detectIpod(); } /** * Detects if the current device is an iPod Touch. */ public boolean detectIpod() { return userAgent.indexOf(deviceIpod) != -1; } /** * Detects if the current device is an iPhone or iPod Touch. */ public boolean detectIphoneOrIpod() { //We repeat the searches here because some iPods may report themselves as an iPhone, which would be okay. return userAgent.indexOf(deviceIphone) != -1 || userAgent.indexOf(deviceIpod) != -1; } /** * Detects if the current device is an Android OS-based device. */ public boolean detectAndroid() { return userAgent.indexOf(deviceAndroid) != -1; } /** * Detects if the current device is an Android OS-based device and * the browser is based on WebKit. */ public boolean detectAndroidWebKit() { return detectAndroid() && detectWebkit(); } /** * Detects if the current browser is based on WebKit. */ public boolean detectWebkit() { return userAgent.indexOf(engineWebKit) != -1; } /** * Detects if the current browser is the S60 Open Source Browser. */ public boolean detectS60OssBrowser() { //First, test for WebKit, then make sure it's either Symbian or S60. return detectWebkit() && (userAgent.indexOf(deviceSymbian) != -1 || userAgent.indexOf(deviceS60) != -1); } /** * * Detects if the current device is any Symbian OS-based device, * including older S60, Series 70, Series 80, Series 90, and UIQ, * or other browsers running on these devices. */ public boolean detectSymbianOS() { return userAgent.indexOf(deviceSymbian) != -1 || userAgent.indexOf(deviceS60) != -1 || userAgent.indexOf(deviceS70) != -1 || userAgent.indexOf(deviceS80) != -1 || userAgent.indexOf(deviceS90) != -1; } /** * Detects if the current browser is a Windows Mobile device. */ public boolean detectWindowsMobile() { //Most devices use 'Windows CE', but some report 'iemobile' // and some older ones report as 'PIE' for Pocket IE. return userAgent.indexOf(deviceWinMob) != -1 || userAgent.indexOf(deviceIeMob) != -1 || userAgent.indexOf(enginePie) != -1 || (detectWapWml() && userAgent.indexOf(deviceWindows) != -1); } /** * Detects if the current browser is a BlackBerry of some sort. */ public boolean detectBlackBerry() { return userAgent.indexOf(deviceBB) != -1 || httpAccept.indexOf(vndRIM) != -1; } /** * Detects if the current browser is a BlackBerry Touch * device, such as the Storm */ public boolean detectBlackBerryTouch() { return userAgent.indexOf(deviceBBStorm) != -1; } /** * Detects if the current browser is on a PalmOS device. */ public boolean detectPalmOS() { //Most devices nowadays report as 'Palm', but some older ones reported as Blazer or Xiino. if (userAgent.indexOf(devicePalm) != -1 || userAgent.indexOf(engineBlazer) != -1 || userAgent.indexOf(engineXiino) != -1 && !detectPalmWebOS()) { //Make sure it's not WebOS first if (detectPalmWebOS()) { return false; } else { return true; } } return false; } /** * Detects if the current browser is on a Palm device * running the new WebOS. */ public boolean detectPalmWebOS() { return userAgent.indexOf(deviceWebOS) != -1; } /** * Check to see whether the device is any device * in the 'smartphone' category. */ public boolean detectSmartphone() { return (detectIphoneOrIpod() || detectS60OssBrowser() || detectSymbianOS() || detectWindowsMobile() || detectBlackBerry() || detectPalmOS() || detectPalmWebOS() || detectAndroid()); } /** * Detects whether the device is a Brew-powered device. */ public boolean detectBrewDevice() { return userAgent.indexOf(deviceBrew) != -1; } /** * Detects the Danger Hiptop device. */ public boolean detectDangerHiptop() { return userAgent.indexOf(deviceDanger) != -1 || userAgent.indexOf(deviceHiptop) != -1; } /** * Detects Opera Mobile or Opera Mini. * Added by AHand */ public boolean detectOperaMobile() { return userAgent.indexOf(engineOpera) != -1 && (userAgent.indexOf(mini) != -1 || userAgent.indexOf(mobi) != -1); } /** * Detects whether the device supports WAP or WML. */ public boolean detectWapWml() { return httpAccept.indexOf(vndwap) != -1 || httpAccept.indexOf(wml) != -1; } /** * The quick way to detect for a mobile device. * Will probably detect most recent/current mid-tier Feature Phones * as well as smartphone-class devices. */ public boolean detectMobileQuick() { //Ordered roughly by market share, WAP/XML > Brew > Smartphone. if (detectWapWml()) { return true; } if (detectBrewDevice()) { return true; } // Updated by AHand if (detectOperaMobile()) { return true; } if (userAgent.indexOf(engineUpBrowser) != -1) { return true; } if (userAgent.indexOf(engineOpenWeb) != -1) { return true; } if (userAgent.indexOf(deviceMidp) != -1) { return true; } if (detectSmartphone()) { return true; } if (detectDangerHiptop()) { return true; } if (detectMidpCapable()) { return true; } if (userAgent.indexOf(devicePda) != -1) { return true; } if (userAgent.indexOf(mobile) != -1) { return true; } //detect older phones from certain manufacturers and operators. if (userAgent.indexOf(uplink) != -1) { return true; } if (userAgent.indexOf(manuSonyEricsson) != -1) { return true; } if (userAgent.indexOf(manuericsson) != -1) { return true; } if (userAgent.indexOf(manuSamsung1) != -1) { return true; } if (userAgent.indexOf(svcDocomo) != -1) { return true; } if (userAgent.indexOf(svcKddi) != -1) { return true; } if (userAgent.indexOf(svcVodafone) != -1) { return true; } return false; } /** * Detects if the current device is a Sony Playstation. */ public boolean detectSonyPlaystation() { return userAgent.indexOf(devicePlaystation) != -1; } /** * Detects if the current device is a Nintendo game device. */ public boolean detectNintendo() { return userAgent.indexOf(deviceNintendo) != -1 || userAgent.indexOf(deviceWii) != -1 || userAgent.indexOf(deviceNintendoDs) != -1; } /** * Detects if the current device is a Microsoft Xbox. */ public boolean detectXbox() { return userAgent.indexOf(deviceXbox) != -1; } /** * Detects if the current device is an Internet-capable game console. */ public boolean detectGameConsole() { return detectSonyPlaystation() || detectNintendo() || detectXbox(); } /** * Detects if the current device supports MIDP, a mobile Java technology. */ public boolean detectMidpCapable() { return userAgent.indexOf(deviceMidp) != -1 || httpAccept.indexOf(deviceMidp) != -1; } /** * Detects if the current device is on one of the Maemo-based Nokia Internet Tablets. */ public boolean detectMaemoTablet() { return (userAgent.indexOf(maemo) != -1 || (userAgent.indexOf(maemoTablet) != -1 && userAgent.indexOf(linux) != -1)); } /** * Detects if the current device is an Archos media player/Internet tablet. */ public boolean detectArchos() { return userAgent.indexOf(deviceArchos) != -1; } /** * Detects if the current browser is a Sony Mylo device. * Updated by AHand */ public boolean detectSonyMylo() { return userAgent.indexOf(manuSony) != -1 && (userAgent.indexOf(qtembedded) != -1 || userAgent.indexOf(mylocom2) != -1); } /** * The longer and more thorough way to detect for a mobile device. * Will probably detect most feature phones, * smartphone-class devices, Internet Tablets, * Internet-enabled game consoles, etc. * This ought to catch a lot of the more obscure and older devices, also -- * but no promises on thoroughness! */ public boolean detectMobileLong() { return detectMobileQuick() || detectMaemoTablet() || detectGameConsole(); } //***************************** // For Desktop Browsers //***************************** public boolean detectMSIE() { return userAgent.indexOf(msie) != -1; } public boolean detectMSIE6() { return userAgent.indexOf(msie60) != -1 && userAgent.indexOf(msie61) != -1; } public boolean detectMSIE7() { return userAgent.indexOf(msie7) != -1; } public boolean detectMSIE8() { return userAgent.indexOf(msie8) != -1; } public boolean detectMSIE9() { return userAgent.indexOf(msie9) != -1; } public boolean detectFirefox() { return userAgent.indexOf(firefox) != -1; } public boolean detectSafari() { return userAgent.indexOf(safari) != -1; } public boolean detectChrome() { return userAgent.indexOf(chrome) != -1; } public boolean detectOpera() { return userAgent.indexOf(opera) != -1; } public boolean detectWindows() { return userAgent.indexOf(windows) != -1; } //***************************** // For Mobile Web Site Design //***************************** /** * The quick way to detect for a tier of devices. * This method detects for devices which can * display iPhone-optimized web content. * Includes iPhone, iPod Touch, Android, Palm WebOS, etc. */ public boolean detectTierIphone() { return detectIphoneOrIpod() || detectPalmWebOS() || detectAndroid() || detectAndroidWebKit(); } /** * The quick way to detect for a tier of devices. * This method detects for all smartphones, but * excludes the iPhone Tier devices. */ public boolean detectTierSmartphones() { return detectSmartphone() && (!detectTierIphone()); } /** * The quick way to detect for a tier of devices. * This method detects for all other types of phones, * but excludes the iPhone and Smartphone Tier devices. */ public boolean detectTierOtherPhones() { return detectMobileQuick() && (!detectTierIphone()) && (!detectTierSmartphones()); } }