content: /* *******************************************
  // Copyright 2010-2015, Anthony Hand
  //
  //
  // File version 2015.05.13 (May 13, 2015)
  // Updates:
  //	- Moved MobileESP to GitHub. https://github.com/ahand/mobileesp
  //	- Opera Mobile/Mini browser has the same UA string on multiple platforms and doesn't differentiate phone vs. tablet. 
  //		- Removed DetectOperaAndroidPhone(). This method is no longer reliable. 
  //		- Removed DetectOperaAndroidTablet(). This method is no longer reliable. 
  //	- Added support for Windows Phone 10: variable and DetectWindowsPhone10()
  //	- Updated DetectWindowsPhone() to include WP10. 
  //	- Added support for Firefox OS.  
  //		- A variable plus DetectFirefoxOS(), DetectFirefoxOSPhone(), DetectFirefoxOSTablet()
  //		- NOTE: Firefox doesn't add UA tokens to definitively identify Firefox OS vs. their browsers on other mobile platforms.
  //	- Added support for Sailfish OS. Not enough info to add a tablet detection method at this time. 
  //		- A variable plus DetectSailfish(), DetectSailfishPhone()
  //	- Added support for Ubuntu Mobile OS. 
  //		- DetectUbuntu(), DetectUbuntuPhone(), DetectUbuntuTablet()
  //	- Added support for 2 smart TV OSes. They lack browsers but do have WebViews for use by HTML apps. 
  //		- One variable for Samsung Tizen TVs, plus DetectTizenTV()
  //		- One variable for LG WebOS TVs, plus DetectWebOSTV()
  //	- Updated DetectTizen(). Now tests for "mobile" to disambiguate from Samsung Smart TVs
  //	- Removed variables for obsolete devices: deviceHtcFlyer, deviceXoom.
  //	- Updated DetectAndroid(). No longer has a special test case for the HTC Flyer tablet. 
  //	- Updated DetectAndroidPhone(). 
  //		- Updated internal detection code for Android. 
  //		- No longer has a special test case for the HTC Flyer tablet. 
  //		- Checks against DetectOperaMobile() on Android and reports here if relevant. 
  //	- Updated DetectAndroidTablet(). 
  //		- No longer has a special test case for the HTC Flyer tablet. 
  //		- Checks against DetectOperaMobile() on Android to exclude it from here.
  //	- DetectMeego(): Changed definition for this method. Now detects any Meego OS device, not just phones. 
  //	- DetectMeegoPhone(): NEW. For Meego phones. Ought to detect Opera browsers on Meego, as well.  
  //	- DetectTierIphone(): Added support for phones running Sailfish, Ubuntu and Firefox Mobile. 
  //	- DetectTierTablet(): Added support for tablets running Ubuntu and Firefox Mobile. 
  //	- DetectSmartphone(): Added support for Meego phones. 
  //	- Refactored the detection logic in DetectMobileQuick() and DetectMobileLong().
  //		- Moved a few detection tests for older browsers to Long. 
  //
  //
  //
  // LICENSE INFORMATION
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //        http://www.apache.org/licenses/LICENSE-2.0
  // Unless required by applicable law or agreed to in writing,
  // software distributed under the License is distributed on an
  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  // either express or implied. See the License for the specific
  // language governing permissions and limitations under the License. 
  //
  //
  // ABOUT THIS PROJECT
  //   Project Owner: Anthony Hand
  //   Email: anthony.hand@gmail.com
  //   Web Site: http://www.mobileesp.com
  //   Source Files: https://github.com/ahand/mobileesp
  //
  //   Versions of this code are available for:
  //      PHP, JavaScript, Java, ASP.NET (C#), and Ruby
  //
  // *******************************************
   */
  package com.handinteractive.mobile;
  
  /**
   * 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 = "";
      
      // Let's store values for quickly accessing the same info multiple times.
      public boolean initCompleted = false;
      public boolean isWebkit = false; //Stores the result of DetectWebkit()
      public boolean isMobilePhone = false; //Stores the result of DetectMobileQuick()
      public boolean isIphone = false; //Stores the result of DetectIphone()
      public boolean isAndroid = false; //Stores the result of DetectAndroid()
      public boolean isAndroidPhone = false; //Stores the result of DetectAndroidPhone()
      public boolean isTierTablet = false; //Stores the result of DetectTierTablet()
      public boolean isTierIphone = false; //Stores the result of DetectTierIphone()
      public boolean isTierRichCss = false; //Stores the result of DetectTierRichCss()
      public boolean isTierGenericMobile = false; //Stores the result of DetectTierOtherPhones()
      
      // Initialize some initial smartphone string variables.
      public static final String engineWebKit = "webkit";
      
      public static final String deviceIphone = "iphone";
      public static final String deviceIpod = "ipod";
      public static final String deviceIpad = "ipad";
      public static final String deviceMacPpc = "macintosh"; //Used for disambiguation
      
      public static final String deviceAndroid = "android";
      public static final String deviceGoogleTV = "googletv";
      
      public static final String deviceWinPhone7 = "windows phone os 7";
      public static final String deviceWinPhone8 = "windows phone 8";
      public static final String deviceWinPhone10 = "windows phone 10";
      public static final String deviceWinMob = "windows ce";
      public static final String deviceWindows = "windows";
      public static final String deviceIeMob = "iemobile";
      public static final String devicePpc = "ppc"; //Stands for PocketPC
      public static final String enginePie = "wm5 pie"; //An old Windows Mobile
      
      public static final String deviceBB = "blackberry";
      public static final String deviceBB10 = "bb10"; //For the new BB 10 OS
      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 deviceBBBold = "blackberry97";  //Bold 97x0 (non-touch)
      public static final String deviceBBBoldTouch = "blackberry 99";  //Bold 99x0 (touchscreen)
      public static final String deviceBBTour = "blackberry96";  //Tour
      public static final String deviceBBCurve = "blackberry89";  //Curve 2
      public static final String deviceBBCurveTouch = "blackberry 938";  //Curve Touch 9380
      public static final String deviceBBTorch = "blackberry 98";  //Torch
      public static final String deviceBBPlaybook = "playbook"; //PlayBook tablet
      
      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 devicePalm = "palm";
      public static final String deviceWebOS = "webos"; //For Palm devices
      public static final String deviceWebOStv = "web0s"; //For LG TVs
      public static final String deviceWebOShp = "hpwos"; //For HP's line of WebOS devices
      
      public static final String deviceNuvifone = "nuvifone";  //Garmin Nuvifone
      public static final String deviceBada = "bada";  //Samsung's Bada OS
      public static final String deviceTizen = "tizen";  //Tizen OS
      public static final String deviceMeego = "meego";  //Meego OS
      public static final String deviceSailfish = "sailfish"; //Sailfish OS
      public static final String deviceUbuntu = "ubuntu"; //Ubuntu Mobile OS
  
      public static final String deviceKindle = "kindle";  //Amazon Kindle, eInk one
      public static final String engineSilk = "silk-accelerated";  //Amazon's accelerated Silk browser for Kindle Fire
      
      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 deviceTablet = "tablet"; //Generic term for slate and tablet devices
      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 devicePlaystationVita = "vita";
      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 engineFirefox = "firefox"; //For Firefox OS
      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 engineTelecaQ = "teleca q"; //a modern feature phone browser
      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.
      
      //Smart TV strings
      public static final String smartTV1 = "smart-tv"; //Samsung Tizen smart TVs
      public static final String smartTV2 = "smarttv"; //LG WebOS smart TVs
  
      //Use Maemo, Tablet, and Linux to test for Nokia"s Internet Tablets.
      public static final String maemo = "maemo";
      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";
      public static final String manuHtc = "htc"; //Popular Android and WinMo manufacturer
      
      //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";
  
      //Disambiguation strings.
      public static final String disUpdate = "update"; //pda vs. update
  
  
      /**
       * 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();
          }
  
          //Intialize key stored values.
          initDeviceScan();
      }
  
      /**
       * Return the lower case HTTP_USER_AGENT
       * @return userAgent
       */
      public String getUserAgent() {
          return userAgent;
      }
  
      /**
       * Return the lower case HTTP_ACCEPT
       * @return httpAccept
       */
      public String getHttpAccept() {
          return httpAccept;
      }
  
      /**
       * Return whether the device is an Iphone or iPod Touch
       * @return isIphone
       */
      public boolean getIsIphone() {
          return isIphone;
      }
  
      /**
       * Return whether the device is in the Tablet Tier.
       * @return isTierTablet
       */
      public boolean getIsTierTablet() {
          return isTierTablet;
      }
  
      /**
       * Return whether the device is in the Iphone Tier.
       * @return isTierIphone
       */
      public boolean getIsTierIphone() {
          return isTierIphone;
      }
  
      /**
       * Return whether the device is in the 'Rich CSS' tier of mobile devices.
       * @return isTierRichCss
       */
      public boolean getIsTierRichCss() {
          return isTierRichCss;
      }
  
      /**
       * Return whether the device is a generic, less-capable mobile device.
       * @return isTierGenericMobile
       */
      public boolean getIsTierGenericMobile() {
          return isTierGenericMobile;
      }
  
      /**
       * Initialize Key Stored Values.
       */
      public void initDeviceScan() {
          //Save these properties to speed processing
          this.isWebkit = detectWebkit();
          this.isIphone = detectIphone();
          this.isAndroid = detectAndroid();
          this.isAndroidPhone = detectAndroidPhone();
          
          //Generally, these tiers are the most useful for web development
          this.isMobilePhone = detectMobileQuick();
          this.isTierTablet = detectTierTablet();
          this.isTierIphone = detectTierIphone();
          
          //Optional: Comment these out if you NEVER use them
          this.isTierRichCss = detectTierRichCss();
          this.isTierGenericMobile = detectTierOtherPhones();
          
          this.initCompleted = true;
      }
  
      /**
       * Detects if the current device is an iPhone.
       * @return detection of an iPhone
       */
      public boolean detectIphone() {
          // The iPad and iPod touch say they're an iPhone! So let's disambiguate.
          if (userAgent.indexOf(deviceIphone) != -1 && 
                  !detectIpad() && 
                  !detectIpod()) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device is an iPod Touch.
       * @return detection of an iPod Touch
       */
      public boolean detectIpod() {
          if (userAgent.indexOf(deviceIpod) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device is an iPad tablet.
       * @return detection of an iPad
       */
      public boolean detectIpad() {
          if (userAgent.indexOf(deviceIpad) != -1
                  && detectWebkit()) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device is an iPhone or iPod Touch.
       * @return detection of 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.
          if (userAgent.indexOf(deviceIphone) != -1
                  || userAgent.indexOf(deviceIpod) != -1) {
              return true;
          }
          return false;
      }
      
      /**
       * Detects *any* iOS device: iPhone, iPod Touch, iPad.
       * @return detection of an Apple iOS device
       */
      public boolean detectIos() {
          if (detectIphoneOrIpod() || detectIpad()) {
              return true;
          }
          return false;
      }
  
  
      /**
       * Detects *any* Android OS-based device: phone, tablet, and multi-media player.
       * Also detects Google TV.
       * @return detection of an Android device
       */
      public boolean detectAndroid() {
          if ((userAgent.indexOf(deviceAndroid) != -1) ||
            detectGoogleTV()) 
              return true;
          
          return false;
      }
  
      /**
       * Detects if the current device is a (small-ish) Android OS-based device
       * used for calling and/or multi-media (like a Samsung Galaxy Player).
       * Google says these devices will have 'Android' AND 'mobile' in user agent.
       * Ignores tablets (Honeycomb and later).
       * @return  detection of an Android phone
       */
      public boolean detectAndroidPhone() {
          //First, let's make sure we're on an Android device.
          if (!detectAndroid())
  			return false;
  
          //If it's Android and has 'mobile' in it, Google says it's a phone.
          if (userAgent.indexOf(mobile) != -1)
              return true;
              
          //Special check for Android devices with Opera Mobile/Mini. They should report here.
          if (detectOperaMobile()) 
              return true;
          
          return false;
      }
  
      /**
       * Detects if the current device is a (self-reported) Android tablet.
       * Google says these devices will have 'Android' and NOT 'mobile' in their user agent.
       * @return detection of an Android tablet
       */
      public boolean detectAndroidTablet() {
          //First, let's make sure we're on an Android device.
          if (!detectAndroid())
  			return false;
  
          //Special check for Android devices with Opera Mobile/Mini. They should NOT report here.
          if (detectOperaMobile()) 
              return false;
      
          //Otherwise, if it's Android and does NOT have 'mobile' in it, Google says it's a tablet.
          if ((userAgent.indexOf(mobile) > -1)) 
              return false;
          else 
  			return true;
      }
  
      /**
       * Detects if the current device is an Android OS-based device and
       * the browser is based on WebKit.
       * @return detection of an Android WebKit browser
       */
      public boolean detectAndroidWebKit() {
          if (detectAndroid() && detectWebkit()) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device is a GoogleTV.
       * @return detection of GoogleTV
       */
      public boolean detectGoogleTV() {
          if (userAgent.indexOf(deviceGoogleTV) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current browser is based on WebKit.
       * @return detection of a WebKit browser
       */
      public boolean detectWebkit() {
          if (userAgent.indexOf(engineWebKit) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current browser is the Symbian S60 Open Source Browser.
       * @return detection of Symbian S60 Browser
       */
      public boolean detectS60OssBrowser() {
          //First, test for WebKit, then make sure it's either Symbian or S60.
          if (detectWebkit()
                  && (userAgent.indexOf(deviceSymbian) != -1
                  || userAgent.indexOf(deviceS60) != -1)) {
              return true;
          }
          return false;
      }
  
      /**
       *
       * 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.
       * @return detection of SymbianOS
       */
      public boolean detectSymbianOS() {
          if (userAgent.indexOf(deviceSymbian) != -1
                  || userAgent.indexOf(deviceS60) != -1
                  || userAgent.indexOf(deviceS70) != -1
                  || userAgent.indexOf(deviceS80) != -1
                  || userAgent.indexOf(deviceS90) != -1) {
              return true;
          }
          return false;
      }
      
      /**
       * Detects if the current browser is a Windows Phone 7.x, 8, or 10 device
       * @return detection of Windows Phone 7.x OR 8
       */
      public boolean detectWindowsPhone() {
          if (detectWindowsPhone7() 
          	|| detectWindowsPhone8()
          	|| detectWindowsPhone10()) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects a Windows Phone 7 device (in mobile browsing mode).
       * @return detection of Windows Phone 7
       */
      public boolean detectWindowsPhone7() {
          if (userAgent.indexOf(deviceWinPhone7) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects a Windows Phone 8 device (in mobile browsing mode).
       * @return detection of Windows Phone 8
       */
      public boolean detectWindowsPhone8() {
          if (userAgent.indexOf(deviceWinPhone8) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects a Windows Phone 10 device (in mobile browsing mode).
       * @return detection of Windows Phone 10
       */
      public boolean detectWindowsPhone10() {
          if (userAgent.indexOf(deviceWinPhone10) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current browser is a Windows Mobile device.
       * Excludes Windows Phone 7.x and 8 devices.
       * Focuses on Windows Mobile 6.xx and earlier.
       * @return detection of Windows Mobile
       */
      public boolean detectWindowsMobile() {
          if (detectWindowsPhone()) {
              return false;
          }
          //Most devices use 'Windows CE', but some report 'iemobile'
          //  and some older ones report as 'PIE' for Pocket IE.
          //  We also look for instances of HTC and Windows for many of their WinMo devices.
          if (userAgent.indexOf(deviceWinMob) != -1
                  || userAgent.indexOf(deviceWinMob) != -1
                  || userAgent.indexOf(deviceIeMob) != -1
                  || userAgent.indexOf(enginePie) != -1
                  || (userAgent.indexOf(manuHtc) != -1 && userAgent.indexOf(deviceWindows) != -1) 
                  || (detectWapWml() && userAgent.indexOf(deviceWindows) != -1)) {
              return true;
          }
          
          //Test for Windows Mobile PPC but not old Macintosh PowerPC.
          if (userAgent.indexOf(devicePpc) != -1 &&
  				!(userAgent.indexOf(deviceMacPpc) != -1))
              return true;
              
          return false;
      }
  
      /**
       * Detects if the current browser is any BlackBerry.
       * Includes BB10 OS, but excludes the PlayBook.
       * @return detection of Blackberry
       */
      public boolean detectBlackBerry() {
          if (userAgent.indexOf(deviceBB) != -1 || 
  			httpAccept.indexOf(vndRIM) != -1) 
              return true;
          
          if (detectBlackBerry10Phone())
              return true;
          
          return false;
      }
  
      /**
       * Detects if the current browser is a BlackBerry 10 OS phone.
       * Excludes tablets.
       * @return detection of a Blackberry 10 device
       */
      public boolean detectBlackBerry10Phone() {
          if (userAgent.indexOf(deviceBB10) != -1 && 
  			userAgent.indexOf(mobile) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current browser is on a BlackBerry tablet device.
       *    Example: PlayBook
       * @return detection of a Blackberry Tablet
       */
      public boolean detectBlackBerryTablet() {
          if (userAgent.indexOf(deviceBBPlaybook) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current browser is a BlackBerry device AND uses a
       *    WebKit-based browser. These are signatures for the new BlackBerry OS 6.
       *    Examples: Torch. Includes the Playbook.
       * @return detection of a Blackberry device with WebKit browser
       */
      public boolean detectBlackBerryWebKit() {
          if (detectBlackBerry() &&
  			userAgent.indexOf(engineWebKit) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current browser is a BlackBerry Touch
       * device, such as the Storm, Torch, and Bold Touch. Excludes the Playbook.
       * @return detection of a Blackberry touchscreen device
       */
      public boolean detectBlackBerryTouch() {
          if (detectBlackBerry() &&
  			(userAgent.indexOf(deviceBBStorm) != -1 ||
  			userAgent.indexOf(deviceBBTorch) != -1 ||
  			userAgent.indexOf(deviceBBBoldTouch) != -1 ||
                          userAgent.indexOf(deviceBBCurveTouch) != -1 )) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current browser is a BlackBerry device AND
       *   has a more capable recent browser. Excludes the Playbook.
       *   Examples, Storm, Bold, Tour, Curve2
       *   Excludes the new BlackBerry OS 6 and 7 browser!!
       * @return detection of a Blackberry device with a better browser
       */
      public boolean detectBlackBerryHigh() {
          //Disambiguate for BlackBerry OS 6 or 7 (WebKit) browser
          if (detectBlackBerryWebKit()) 
  			return false;
          if (detectBlackBerry()) {
              if (detectBlackBerryTouch()
                      || userAgent.indexOf(deviceBBBold) != -1
                      || userAgent.indexOf(deviceBBTour) != -1
                      || userAgent.indexOf(deviceBBCurve) != -1) {
                  return true;
              } else {
                  return false;
              }
          } else {
              return false;
          }
      }
  
      /**
       * Detects if the current browser is a BlackBerry device AND
       *   has an older, less capable browser.
       *   Examples: Pearl, 8800, Curve1
       * @return detection of a Blackberry device with a poorer browser
       */
      public boolean detectBlackBerryLow() {
          if (detectBlackBerry()) {
              //Assume that if it's not in the High tier, then it's Low
              if (detectBlackBerryHigh()
  					|| detectBlackBerryWebKit()) {
                  return false;
              } else {
                  return true;
              }
          } else {
              return false;
          }
      }
  
      /**
       * Detects if the current browser is on a PalmOS device.
       * @return detection of 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) {
              //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.
       * @return detection of a Palm WebOS device
       */
      public boolean detectPalmWebOS() {
          if (userAgent.indexOf(deviceWebOS) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current browser is on an HP tablet running WebOS.
       * @return detection of an HP WebOS tablet
       */
      public boolean detectWebOSTablet() {
          if (userAgent.indexOf(deviceWebOShp) != -1 && 
                  userAgent.indexOf(deviceTablet) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current browser is on a WebOS smart TV.
       * @return detection of a WebOS smart TV
       */
      public boolean detectWebOSTV() {
          if (userAgent.indexOf(deviceWebOStv) != -1 && 
                  userAgent.indexOf(smartTV2) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects Opera Mobile or Opera Mini.
       * @return detection of an Opera browser for a mobile device
       */
      public boolean detectOperaMobile() {
          if (userAgent.indexOf(engineOpera) != -1
                  && (userAgent.indexOf(mini) != -1
                  || userAgent.indexOf(mobi) != -1)) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device is an Amazon Kindle (eInk devices only).
       * Note: For the Kindle Fire, use the normal Android methods.
       * @return detection of a Kindle
       */
      public boolean detectKindle() {
          if (userAgent.indexOf(deviceKindle)!= -1 &&
              !detectAndroid()) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current Amazon device is using the Silk Browser.
       * Note: Typically used by the the Kindle Fire.
       * @return detection of an Amazon Kindle Fire in Silk mode.
       */
      public boolean detectAmazonSilk() {
          if (userAgent.indexOf(engineSilk)  != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current browser is a
       *    Garmin Nuvifone.
       * @return detection of a Garmin Nuvifone
       */
      public boolean detectGarminNuvifone() {
          if (userAgent.indexOf(deviceNuvifone) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects a device running the Bada OS from Samsung.
       * @return detection of a Bada device
       */
      public boolean detectBada() {
          if (userAgent.indexOf(deviceBada) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects a device running the Tizen smartphone OS.
       * @return detection of a Tizen device
       */
      public boolean detectTizen() {
          if (userAgent.indexOf(deviceTizen) != -1 && 
                  userAgent.indexOf(mobile) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current browser is on a Tizen smart TV.
       * @return detection of a Tizen smart TV
       */
      public boolean detectTizenTV() {
          if (userAgent.indexOf(deviceTizen) != -1 && 
                  userAgent.indexOf(smartTV1) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects a device running the Meego OS.
       * @return detection of a Meego device
       */
      public boolean detectMeego() {
          if (userAgent.indexOf(deviceMeego) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects a phone running the Meego OS.
       * @return detection of a Meego phone
       */
      public boolean detectMeegoPhone() {
          if (userAgent.indexOf(deviceMeego) != -1 && 
                  userAgent.indexOf(mobi) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects a mobile device (probably) running the Firefox OS.
       * @return detection of a Firefox OS mobile device
       */
      public boolean detectFirefoxOS() {
          if (detectFirefoxOSPhone() || detectFirefoxOSTablet()) 
              return true;
          
          return false;
      }
  
      /**
       * Detects a phone (probably) running the Firefox OS.
       * @return detection of a Firefox OS phone
       */
      public boolean detectFirefoxOSPhone() {
          //First, let's make sure we're NOT on another major mobile OS.
          if (detectIos() 
          	|| detectAndroid()
          	|| detectSailfish())
              return false;
          
          if ((userAgent.indexOf(engineFirefox) != -1) 
          	&& (userAgent.indexOf(mobile) != -1)) 
              return true;
          
          return false;
      }
  
      /**
       * Detects a tablet (probably) running the Firefox OS.
       * @return detection of a Firefox OS tablet
       */
      public boolean detectFirefoxOSTablet() {
          //First, let's make sure we're NOT on another major mobile OS.
          if (detectIos() 
          	|| detectAndroid()
          	|| detectSailfish())
              return false;
          
          if ((userAgent.indexOf(engineFirefox) != -1) 
          	&& (userAgent.indexOf(deviceTablet) != -1)) 
              return true;
          
          return false;
      }
  
      /**
       * Detects a device running the Sailfish OS.
       * @return detection of a Sailfish device
       */
      public boolean detectSailfish() {
          if (userAgent.indexOf(deviceSailfish) != -1) {
              return true;
          }
          return false;
      }
      
      /**
       * Detects a phone running the Sailfish OS.
       * @return detection of a Sailfish phone
       */
      public boolean detectSailfishPhone() {
          if (detectSailfish() && (userAgent.indexOf(mobile) != -1)) 
              return true;
          
          return false;
      }
  
      /**
       * Detects a mobile device running the Ubuntu Mobile OS.
       * @return detection of an Ubuntu Mobile OS mobile device
       */
      public boolean detectUbuntu() {
          if (detectUbuntuPhone() || detectUbuntuTablet()) 
              return true;
          
          return false;
      }
  
      /**
       * Detects a phone running the Ubuntu Mobile OS.
       * @return detection of an Ubuntu Mobile OS phone
       */
      public boolean detectUbuntuPhone() {
          if ((userAgent.indexOf(deviceUbuntu) != -1) 
          	&& (userAgent.indexOf(mobile) != -1)) 
              return true;
          
          return false;
      }
  
      /**
       * Detects a tablet running the Ubuntu Mobile OS.
       * @return detection of an Ubuntu Mobile OS tablet
       */
      public boolean detectUbuntuTablet() {
          if ((userAgent.indexOf(deviceUbuntu) != -1) 
          	&& (userAgent.indexOf(deviceTablet) != -1)) 
              return true;
          
          return false;
      }
  
  
      /**
       * Detects the Danger Hiptop device.
       * @return detection of a Danger Hiptop
       */
      public boolean detectDangerHiptop() {
          if (userAgent.indexOf(deviceDanger) != -1
                  || userAgent.indexOf(deviceHiptop) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current browser is a Sony Mylo device.
       * @return detection of a Sony Mylo device
       */
      public boolean detectSonyMylo() {
          if (userAgent.indexOf(manuSony) != -1
                  && (userAgent.indexOf(qtembedded) != -1
                  || userAgent.indexOf(mylocom2) != -1)) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device is on one of the Maemo-based Nokia Internet Tablets.
       * @return detection of a Maemo OS tablet
       */
      public boolean detectMaemoTablet() {
          if (userAgent.indexOf(maemo) != -1) {
              return true;
          } else if (userAgent.indexOf(linux) != -1
                  && userAgent.indexOf(deviceTablet) != -1
                  && !detectWebOSTablet()
                  && !detectAndroid()) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device is an Archos media player/Internet tablet.
       * @return detection of an Archos media player
       */
      public boolean detectArchos() {
          if (userAgent.indexOf(deviceArchos) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device is an Internet-capable game console.
       * Includes many handheld consoles.
       * @return detection of any Game Console
       */
      public boolean detectGameConsole() {
          if (detectSonyPlaystation()
                  || detectNintendo()
                  || detectXbox()) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device is a Sony Playstation.
       * @return detection of Sony Playstation
       */
      public boolean detectSonyPlaystation() {
          if (userAgent.indexOf(devicePlaystation) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device is a handheld gaming device with
       * a touchscreen and modern iPhone-class browser. Includes the Playstation Vita.
       * @return detection of a handheld gaming device
       */
      public boolean detectGamingHandheld() {
          if ((userAgent.indexOf(devicePlaystation) != -1) &&
              (userAgent.indexOf(devicePlaystationVita) != -1)) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device is a Nintendo game device.
       * @return detection of Nintendo
       */
      public boolean detectNintendo() {
          if (userAgent.indexOf(deviceNintendo) != -1
                  || userAgent.indexOf(deviceWii) != -1
                  || userAgent.indexOf(deviceNintendoDs) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device is a Microsoft Xbox.
       * @return detection of Xbox
       */
      public boolean detectXbox() {
          if (userAgent.indexOf(deviceXbox) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects whether the device is a Brew-powered device.
       * @return detection of a Brew device
       */
      public boolean detectBrewDevice() {
          if (userAgent.indexOf(deviceBrew) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects whether the device supports WAP or WML.
       * @return detection of a WAP- or WML-capable device
       */
      public boolean detectWapWml() {
          if (httpAccept.indexOf(vndwap) != -1
                  || httpAccept.indexOf(wml) != -1) {
              return true;
          }
          return false;
      }
  
      /**
       * Detects if the current device supports MIDP, a mobile Java technology.
       * @return detection of a MIDP mobile Java-capable device
       */
      public boolean detectMidpCapable() {
          if (userAgent.indexOf(deviceMidp) != -1
                  || httpAccept.indexOf(deviceMidp) != -1) {
              return true;
          }
          return false;
      }
  
  
  
    //*****************************
    // Device Classes
    //*****************************
  
      /**
       * Check to see whether the device is any device
       *   in the 'smartphone' category.
       * @return detection of a general smartphone device
       */
      public boolean detectSmartphone() {
          //Exclude duplicates from TierIphone
          return (detectTierIphone() 
                  || detectS60OssBrowser()
                  || detectSymbianOS()
                  || detectWindowsMobile()
                  || detectBlackBerry()
                  || detectMeegoPhone()
                  || detectPalmOS());
      }
  
      /**
       *	Detects if the current device is a mobile device.
       *  This method catches most of the popular modern devices. 
       *  Excludes Apple iPads and other modern tablets.
       * @return detection of any mobile device using the quicker method
       */
      public boolean detectMobileQuick() {
          //Let's exclude tablets
          if (isTierTablet) {
              return false;
          }
          //Most mobile browsing is done on smartphones
          if (detectSmartphone()) {
              return true;
          }
  
          //Catch-all for many mobile devices
          if (userAgent.indexOf(mobile) != -1) {
              return true;
          }
  
          if (detectOperaMobile()) {
              return true;
          }
  
          //We also look for Kindle devices
          if (detectKindle()
              || detectAmazonSilk()) {
              return true;
          }
  
          if (detectWapWml()
  			|| detectMidpCapable()
  			|| detectBrewDevice()) {
              return true;
          }
  
          if ((userAgent.indexOf(engineNetfront) != -1) 
  			|| (userAgent.indexOf(engineUpBrowser) != -1)) {
              return true;
          }
  
          return false;
      }
  
      /**
       * 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!
       * @return detection of any mobile device using the more thorough method
       */
      public boolean detectMobileLong() {
          if (detectMobileQuick()
                  || detectGameConsole()) {
              return true;
          }
  
          if (detectDangerHiptop()
  			|| detectMaemoTablet()
              || detectSonyMylo()
  			|| detectArchos()) {
              return true;
          }
  
          if ((userAgent.indexOf(devicePda) != -1) &&
  			(userAgent.indexOf(disUpdate) < 0)) //no index found
          {
              return true;
          }
  
          //Detect older phones from certain manufacturers and operators.
          if ((userAgent.indexOf(uplink) != -1) 
          	|| (userAgent.indexOf(engineOpenWeb) != -1) 
          	|| (userAgent.indexOf(manuSamsung1) != -1)
          	|| (userAgent.indexOf(manuSonyEricsson) != -1)
          	|| (userAgent.indexOf(manuericsson) != -1)
          	|| (userAgent.indexOf(svcDocomo) != -1)
          	|| (userAgent.indexOf(svcKddi) != -1)
          	|| (userAgent.indexOf(svcVodafone) != -1))
          	{
              	return true;
          	}
          
          return false;
      }
  
      //*****************************
      // For Mobile Web Site Design
      //*****************************
      
      /**
       * The quick way to detect for a tier of devices.
       *   This method detects for the new generation of
       *   HTML 5 capable, larger screen tablets.
       *   Includes iPad, Android (e.g., Xoom), BB Playbook, WebOS, etc.
       * @return detection of any device in the Tablet Tier
       */
      public boolean detectTierTablet() {
          if (detectIpad()
                  || detectAndroidTablet()
                  || detectBlackBerryTablet()
                  || detectFirefoxOSTablet()
                  || detectUbuntuTablet()
                  || detectWebOSTablet()) {
              return true;
          }
          return false;
      }
  
      /**
       * 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, Windows Phone 7 and 8, BB10, WebOS, Playstation Vita, etc.
       * @return detection of any device in the iPhone/Android/Windows Phone/BlackBerry/WebOS Tier
       */
      public boolean detectTierIphone() {
          if (detectIphoneOrIpod()
                  || detectAndroidPhone()
                  || detectWindowsPhone()
                  || detectBlackBerry10Phone()
                  || (detectBlackBerryWebKit() 
  					&& detectBlackBerryTouch())
                  || detectPalmWebOS()
                  || detectBada()
                  || detectTizen()
                  || detectFirefoxOSPhone()
                  || detectSailfishPhone()
                  || detectUbuntuPhone()
                  || detectGamingHandheld()) {
              return true;
          }
          return false;
      }
  
      /**
       * The quick way to detect for a tier of devices.
       *   This method detects for devices which are likely to be capable
       *   of viewing CSS content optimized for the iPhone,
       *   but may not necessarily support JavaScript.
       *   Excludes all iPhone Tier devices.
       * @return detection of any device in the 'Rich CSS' Tier
       */
      public boolean detectTierRichCss() {
  		boolean result = false;
  		//The following devices are explicitly ok.
  		//Note: 'High' BlackBerry devices ONLY
  		if (detectMobileQuick()) {
  
              //Exclude iPhone Tier and e-Ink Kindle devices.
  			if (!detectTierIphone() && !detectKindle()) {
  
  				//The following devices are explicitly ok.
  				//Note: 'High' BlackBerry devices ONLY
  				//Older Windows 'Mobile' isn't good enough for iPhone Tier.
  				if (detectWebkit()
  					|| detectS60OssBrowser()
  					|| detectBlackBerryHigh()
  					|| detectWindowsMobile()
  					|| userAgent.indexOf(engineTelecaQ) != -1) {
  					   result= true;
  				} // if detectWebkit()
  			} //if !detectTierIphone()
  		} //if detectMobileQuick()
  		return result;
      }
  
      /**
       * The quick way to detect for a tier of devices.
       *   This method detects for all other types of phones,
       *   but excludes the iPhone and RichCSS Tier devices.
       * @return detection of a mobile device in the less capable tier 
       */
      public boolean detectTierOtherPhones() {
          //Exclude devices in the other 2 categories
          if (detectMobileLong() 
  			&& !detectTierIphone() 
  			&& !detectTierRichCss()) {
              return true;
          }
          return false;
      }
  }
  