001/* ******************************************* 002// Copyright 2010-2015, Anthony Hand 003// 004// 005// File version 2015.05.13 (May 13, 2015) 006// Updates: 007// - Moved MobileESP to GitHub. https://github.com/ahand/mobileesp 008// - Opera Mobile/Mini browser has the same UA string on multiple platforms and doesn't differentiate phone vs. tablet. 009// - Removed DetectOperaAndroidPhone(). This method is no longer reliable. 010// - Removed DetectOperaAndroidTablet(). This method is no longer reliable. 011// - Added support for Windows Phone 10: variable and DetectWindowsPhone10() 012// - Updated DetectWindowsPhone() to include WP10. 013// - Added support for Firefox OS. 014// - A variable plus DetectFirefoxOS(), DetectFirefoxOSPhone(), DetectFirefoxOSTablet() 015// - NOTE: Firefox doesn't add UA tokens to definitively identify Firefox OS vs. their browsers on other mobile platforms. 016// - Added support for Sailfish OS. Not enough info to add a tablet detection method at this time. 017// - A variable plus DetectSailfish(), DetectSailfishPhone() 018// - Added support for Ubuntu Mobile OS. 019// - DetectUbuntu(), DetectUbuntuPhone(), DetectUbuntuTablet() 020// - Added support for 2 smart TV OSes. They lack browsers but do have WebViews for use by HTML apps. 021// - One variable for Samsung Tizen TVs, plus DetectTizenTV() 022// - One variable for LG WebOS TVs, plus DetectWebOSTV() 023// - Updated DetectTizen(). Now tests for "mobile" to disambiguate from Samsung Smart TVs 024// - Removed variables for obsolete devices: deviceHtcFlyer, deviceXoom. 025// - Updated DetectAndroid(). No longer has a special test case for the HTC Flyer tablet. 026// - Updated DetectAndroidPhone(). 027// - Updated internal detection code for Android. 028// - No longer has a special test case for the HTC Flyer tablet. 029// - Checks against DetectOperaMobile() on Android and reports here if relevant. 030// - Updated DetectAndroidTablet(). 031// - No longer has a special test case for the HTC Flyer tablet. 032// - Checks against DetectOperaMobile() on Android to exclude it from here. 033// - DetectMeego(): Changed definition for this method. Now detects any Meego OS device, not just phones. 034// - DetectMeegoPhone(): NEW. For Meego phones. Ought to detect Opera browsers on Meego, as well. 035// - DetectTierIphone(): Added support for phones running Sailfish, Ubuntu and Firefox Mobile. 036// - DetectTierTablet(): Added support for tablets running Ubuntu and Firefox Mobile. 037// - DetectSmartphone(): Added support for Meego phones. 038// - Refactored the detection logic in DetectMobileQuick() and DetectMobileLong(). 039// - Moved a few detection tests for older browsers to Long. 040// 041// 042// 043// LICENSE INFORMATION 044// Licensed under the Apache License, Version 2.0 (the "License"); 045// you may not use this file except in compliance with the License. 046// You may obtain a copy of the License at 047// http://www.apache.org/licenses/LICENSE-2.0 048// Unless required by applicable law or agreed to in writing, 049// software distributed under the License is distributed on an 050// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 051// either express or implied. See the License for the specific 052// language governing permissions and limitations under the License. 053// 054// 055// ABOUT THIS PROJECT 056// Project Owner: Anthony Hand 057// Email: anthony.hand@gmail.com 058// Web Site: http://www.mobileesp.com 059// Source Files: https://github.com/ahand/mobileesp 060// 061// Versions of this code are available for: 062// PHP, JavaScript, Java, ASP.NET (C#), and Ruby 063// 064// ******************************************* 065 */ 066 067package org.opencms.jsp.util; 068 069/** 070 * The DetectSmartPhone class encapsulates information about 071 * a browser's connection to your web site. 072 * You can use it to find out whether the browser asking for 073 * your site's content is probably running on a mobile device. 074 * The methods were written so you can be as granular as you want. 075 * For example, enquiring whether it's as specific as an iPod Touch or 076 * as general as a smartphone class device. 077 * The object's methods return true, or false. 078 */ 079@SuppressWarnings("all") // keeps the external code as unchanged as possible 080public class UAgentInfo { 081 // User-Agent and Accept HTTP request headers 082 083 // Initialize some initial smartphone string variables. 084 public static final String engineWebKit = "webkit"; 085 public static final String deviceIphone = "iphone"; 086 087 public static final String deviceIpod = "ipod"; 088 public static final String deviceIpad = "ipad"; 089 public static final String deviceMacPpc = "macintosh"; //Used for disambiguation 090 public static final String deviceAndroid = "android"; 091 public static final String deviceGoogleTV = "googletv"; 092 public static final String deviceWinPhone7 = "windows phone os 7"; 093 public static final String deviceWinPhone8 = "windows phone 8"; 094 public static final String deviceWinPhone10 = "windows phone 10"; 095 public static final String deviceWinMob = "windows ce"; 096 public static final String deviceWindows = "windows"; 097 098 public static final String deviceIeMob = "iemobile"; 099 100 public static final String devicePpc = "ppc"; //Stands for PocketPC 101 public static final String enginePie = "wm5 pie"; //An old Windows Mobile 102 public static final String deviceBB = "blackberry"; 103 public static final String deviceBB10 = "bb10"; //For the new BB 10 OS 104 105 public static final String vndRIM = "vnd.rim"; //Detectable when BB devices emulate IE or Firefox 106 public static final String deviceBBStorm = "blackberry95"; //Storm 1 and 2 107 108 public static final String deviceBBBold = "blackberry97"; //Bold 97x0 (non-touch) 109 public static final String deviceBBBoldTouch = "blackberry 99"; //Bold 99x0 (touchscreen) 110 public static final String deviceBBTour = "blackberry96"; //Tour 111 public static final String deviceBBCurve = "blackberry89"; //Curve 2 112 public static final String deviceBBCurveTouch = "blackberry 938"; //Curve Touch 9380 113 public static final String deviceBBTorch = "blackberry 98"; //Torch 114 public static final String deviceBBPlaybook = "playbook"; //PlayBook tablet 115 public static final String deviceSymbian = "symbian"; 116 117 public static final String deviceS60 = "series60"; 118 public static final String deviceS70 = "series70"; 119 public static final String deviceS80 = "series80"; 120 public static final String deviceS90 = "series90"; 121 public static final String devicePalm = "palm"; 122 public static final String deviceWebOS = "webos"; //For Palm devices 123 public static final String deviceWebOStv = "web0s"; //For LG TVs 124 public static final String deviceWebOShp = "hpwos"; //For HP's line of WebOS devices 125 public static final String deviceNuvifone = "nuvifone"; //Garmin Nuvifone 126 public static final String deviceBada = "bada"; //Samsung's Bada OS 127 public static final String deviceTizen = "tizen"; //Tizen OS 128 129 public static final String deviceMeego = "meego"; //Meego OS 130 public static final String deviceSailfish = "sailfish"; //Sailfish OS 131 public static final String deviceUbuntu = "ubuntu"; //Ubuntu Mobile OS 132 public static final String deviceKindle = "kindle"; //Amazon Kindle, eInk one 133 public static final String engineSilk = "silk-accelerated"; //Amazon's accelerated Silk browser for Kindle Fire 134 135 public static final String engineBlazer = "blazer"; //Old Palm 136 public static final String engineXiino = "xiino"; //Another old Palm 137 //Initialize variables for mobile-specific content. 138 public static final String vndwap = "vnd.wap"; 139 public static final String wml = "wml"; 140 141 //Initialize variables for other random devices and mobile browsers. 142 public static final String deviceTablet = "tablet"; //Generic term for slate and tablet devices 143 public static final String deviceBrew = "brew"; 144 public static final String deviceDanger = "danger"; 145 public static final String deviceHiptop = "hiptop"; 146 public static final String devicePlaystation = "playstation"; 147 public static final String devicePlaystationVita = "vita"; 148 149 public static final String deviceNintendoDs = "nitro"; 150 public static final String deviceNintendo = "nintendo"; 151 152 public static final String deviceWii = "wii"; 153 public static final String deviceXbox = "xbox"; 154 155 public static final String deviceArchos = "archos"; 156 public static final String engineFirefox = "firefox"; //For Firefox OS 157 158 public static final String engineOpera = "opera"; //Popular browser 159 public static final String engineNetfront = "netfront"; //Common embedded OS browser 160 public static final String engineUpBrowser = "up.browser"; //common on some phones 161 public static final String engineOpenWeb = "openweb"; //Transcoding by OpenWave server 162 public static final String deviceMidp = "midp"; //a mobile Java technology 163 public static final String uplink = "up.link"; 164 public static final String engineTelecaQ = "teleca q"; //a modern feature phone browser 165 public static final String devicePda = "pda"; //some devices report themselves as PDAs 166 public static final String mini = "mini"; //Some mobile browsers put "mini" in their names. 167 public static final String mobile = "mobile"; //Some mobile browsers put "mobile" in their user agent strings. 168 public static final String mobi = "mobi"; //Some mobile browsers put "mobi" in their user agent strings. 169 170 //Smart TV strings 171 public static final String smartTV1 = "smart-tv"; //Samsung Tizen smart TVs 172 public static final String smartTV2 = "smarttv"; //LG WebOS smart TVs 173 //Use Maemo, Tablet, and Linux to test for Nokia"s Internet Tablets. 174 public static final String maemo = "maemo"; 175 public static final String linux = "linux"; 176 public static final String qtembedded = "qt embedded"; //for Sony Mylo 177 public static final String mylocom2 = "com2"; //for Sony Mylo also 178 //In some UserAgents, the only clue is the manufacturer. 179 public static final String manuSonyEricsson = "sonyericsson"; 180 public static final String manuericsson = "ericsson"; 181 public static final String manuSamsung1 = "sec-sgh"; 182 public static final String manuSony = "sony"; 183 public static final String manuHtc = "htc"; //Popular Android and WinMo manufacturer 184 //In some UserAgents, the only clue is the operator. 185 public static final String svcDocomo = "docomo"; 186 187 public static final String svcKddi = "kddi"; 188 public static final String svcVodafone = "vodafone"; 189 190 //Disambiguation strings. 191 public static final String disUpdate = "update"; //pda vs. update 192 private String userAgent = ""; 193 private String httpAccept = ""; 194 // Let's store values for quickly accessing the same info multiple times. 195 public boolean initCompleted = false; 196 197 public boolean isWebkit = false; //Stores the result of DetectWebkit() 198 public boolean isMobilePhone = false; //Stores the result of DetectMobileQuick() 199 public boolean isIphone = false; //Stores the result of DetectIphone() 200 public boolean isAndroid = false; //Stores the result of DetectAndroid() 201 public boolean isAndroidPhone = false; //Stores the result of DetectAndroidPhone() 202 203 public boolean isTierTablet = false; //Stores the result of DetectTierTablet() 204 public boolean isTierIphone = false; //Stores the result of DetectTierIphone() 205 public boolean isTierRichCss = false; //Stores the result of DetectTierRichCss() 206 207 public boolean isTierGenericMobile = false; //Stores the result of DetectTierOtherPhones() 208 209 /** 210 * Initialize the userAgent and httpAccept variables 211 * 212 * @param userAgent the User-Agent header 213 * @param httpAccept the Accept header 214 */ 215 public UAgentInfo(String userAgent, String httpAccept) { 216 217 if (userAgent != null) { 218 this.userAgent = userAgent.toLowerCase(); 219 } 220 if (httpAccept != null) { 221 this.httpAccept = httpAccept.toLowerCase(); 222 } 223 224 //Intialize key stored values. 225 initDeviceScan(); 226 } 227 228 /** 229 * Detects if the current Amazon device is using the Silk Browser. 230 * Note: Typically used by the the Kindle Fire. 231 * @return detection of an Amazon Kindle Fire in Silk mode. 232 */ 233 public boolean detectAmazonSilk() { 234 235 if (userAgent.indexOf(engineSilk) != -1) { 236 return true; 237 } 238 return false; 239 } 240 241 /** 242 * Detects *any* Android OS-based device: phone, tablet, and multi-media player. 243 * Also detects Google TV. 244 * @return detection of an Android device 245 */ 246 public boolean detectAndroid() { 247 248 if ((userAgent.indexOf(deviceAndroid) != -1) || detectGoogleTV()) { 249 return true; 250 } 251 252 return false; 253 } 254 255 /** 256 * Detects if the current device is a (small-ish) Android OS-based device 257 * used for calling and/or multi-media (like a Samsung Galaxy Player). 258 * Google says these devices will have 'Android' AND 'mobile' in user agent. 259 * Ignores tablets (Honeycomb and later). 260 * @return detection of an Android phone 261 */ 262 public boolean detectAndroidPhone() { 263 264 //First, let's make sure we're on an Android device. 265 if (!detectAndroid()) { 266 return false; 267 } 268 269 //If it's Android and has 'mobile' in it, Google says it's a phone. 270 if (userAgent.indexOf(mobile) != -1) { 271 return true; 272 } 273 274 //Special check for Android devices with Opera Mobile/Mini. They should report here. 275 if (detectOperaMobile()) { 276 return true; 277 } 278 279 return false; 280 } 281 282 /** 283 * Detects if the current device is a (self-reported) Android tablet. 284 * Google says these devices will have 'Android' and NOT 'mobile' in their user agent. 285 * @return detection of an Android tablet 286 */ 287 public boolean detectAndroidTablet() { 288 289 //First, let's make sure we're on an Android device. 290 if (!detectAndroid()) { 291 return false; 292 } 293 294 //Special check for Android devices with Opera Mobile/Mini. They should NOT report here. 295 if (detectOperaMobile()) { 296 return false; 297 } 298 299 //Otherwise, if it's Android and does NOT have 'mobile' in it, Google says it's a tablet. 300 if ((userAgent.indexOf(mobile) > -1)) { 301 return false; 302 } else { 303 return true; 304 } 305 } 306 307 /** 308 * Detects if the current device is an Android OS-based device and 309 * the browser is based on WebKit. 310 * @return detection of an Android WebKit browser 311 */ 312 public boolean detectAndroidWebKit() { 313 314 if (detectAndroid() && detectWebkit()) { 315 return true; 316 } 317 return false; 318 } 319 320 /** 321 * Detects if the current device is an Archos media player/Internet tablet. 322 * @return detection of an Archos media player 323 */ 324 public boolean detectArchos() { 325 326 if (userAgent.indexOf(deviceArchos) != -1) { 327 return true; 328 } 329 return false; 330 } 331 332 /** 333 * Detects a device running the Bada OS from Samsung. 334 * @return detection of a Bada device 335 */ 336 public boolean detectBada() { 337 338 if (userAgent.indexOf(deviceBada) != -1) { 339 return true; 340 } 341 return false; 342 } 343 344 /** 345 * Detects if the current browser is any BlackBerry. 346 * Includes BB10 OS, but excludes the PlayBook. 347 * @return detection of Blackberry 348 */ 349 public boolean detectBlackBerry() { 350 351 if ((userAgent.indexOf(deviceBB) != -1) || (httpAccept.indexOf(vndRIM) != -1)) { 352 return true; 353 } 354 355 if (detectBlackBerry10Phone()) { 356 return true; 357 } 358 359 return false; 360 } 361 362 /** 363 * Detects if the current browser is a BlackBerry 10 OS phone. 364 * Excludes tablets. 365 * @return detection of a Blackberry 10 device 366 */ 367 public boolean detectBlackBerry10Phone() { 368 369 if ((userAgent.indexOf(deviceBB10) != -1) && (userAgent.indexOf(mobile) != -1)) { 370 return true; 371 } 372 return false; 373 } 374 375 /** 376 * Detects if the current browser is a BlackBerry device AND 377 * has a more capable recent browser. Excludes the Playbook. 378 * Examples, Storm, Bold, Tour, Curve2 379 * Excludes the new BlackBerry OS 6 and 7 browser!! 380 * @return detection of a Blackberry device with a better browser 381 */ 382 public boolean detectBlackBerryHigh() { 383 384 //Disambiguate for BlackBerry OS 6 or 7 (WebKit) browser 385 if (detectBlackBerryWebKit()) { 386 return false; 387 } 388 if (detectBlackBerry()) { 389 if (detectBlackBerryTouch() 390 || (userAgent.indexOf(deviceBBBold) != -1) 391 || (userAgent.indexOf(deviceBBTour) != -1) 392 || (userAgent.indexOf(deviceBBCurve) != -1)) { 393 return true; 394 } else { 395 return false; 396 } 397 } else { 398 return false; 399 } 400 } 401 402 /** 403 * Detects if the current browser is a BlackBerry device AND 404 * has an older, less capable browser. 405 * Examples: Pearl, 8800, Curve1 406 * @return detection of a Blackberry device with a poorer browser 407 */ 408 public boolean detectBlackBerryLow() { 409 410 if (detectBlackBerry()) { 411 //Assume that if it's not in the High tier, then it's Low 412 if (detectBlackBerryHigh() || detectBlackBerryWebKit()) { 413 return false; 414 } else { 415 return true; 416 } 417 } else { 418 return false; 419 } 420 } 421 422 /** 423 * Detects if the current browser is on a BlackBerry tablet device. 424 * Example: PlayBook 425 * @return detection of a Blackberry Tablet 426 */ 427 public boolean detectBlackBerryTablet() { 428 429 if (userAgent.indexOf(deviceBBPlaybook) != -1) { 430 return true; 431 } 432 return false; 433 } 434 435 /** 436 * Detects if the current browser is a BlackBerry Touch 437 * device, such as the Storm, Torch, and Bold Touch. Excludes the Playbook. 438 * @return detection of a Blackberry touchscreen device 439 */ 440 public boolean detectBlackBerryTouch() { 441 442 if (detectBlackBerry() 443 && ((userAgent.indexOf(deviceBBStorm) != -1) 444 || (userAgent.indexOf(deviceBBTorch) != -1) 445 || (userAgent.indexOf(deviceBBBoldTouch) != -1) 446 || (userAgent.indexOf(deviceBBCurveTouch) != -1))) { 447 return true; 448 } 449 return false; 450 } 451 452 /** 453 * Detects if the current browser is a BlackBerry device AND uses a 454 * WebKit-based browser. These are signatures for the new BlackBerry OS 6. 455 * Examples: Torch. Includes the Playbook. 456 * @return detection of a Blackberry device with WebKit browser 457 */ 458 public boolean detectBlackBerryWebKit() { 459 460 if (detectBlackBerry() && (userAgent.indexOf(engineWebKit) != -1)) { 461 return true; 462 } 463 return false; 464 } 465 466 /** 467 * Detects whether the device is a Brew-powered device. 468 * @return detection of a Brew device 469 */ 470 public boolean detectBrewDevice() { 471 472 if (userAgent.indexOf(deviceBrew) != -1) { 473 return true; 474 } 475 return false; 476 } 477 478 /** 479 * Detects the Danger Hiptop device. 480 * @return detection of a Danger Hiptop 481 */ 482 public boolean detectDangerHiptop() { 483 484 if ((userAgent.indexOf(deviceDanger) != -1) || (userAgent.indexOf(deviceHiptop) != -1)) { 485 return true; 486 } 487 return false; 488 } 489 490 /** 491 * Detects a mobile device (probably) running the Firefox OS. 492 * @return detection of a Firefox OS mobile device 493 */ 494 public boolean detectFirefoxOS() { 495 496 if (detectFirefoxOSPhone() || detectFirefoxOSTablet()) { 497 return true; 498 } 499 500 return false; 501 } 502 503 /** 504 * Detects a phone (probably) running the Firefox OS. 505 * @return detection of a Firefox OS phone 506 */ 507 public boolean detectFirefoxOSPhone() { 508 509 //First, let's make sure we're NOT on another major mobile OS. 510 if (detectIos() || detectAndroid() || detectSailfish()) { 511 return false; 512 } 513 514 if ((userAgent.indexOf(engineFirefox) != -1) && (userAgent.indexOf(mobile) != -1)) { 515 return true; 516 } 517 518 return false; 519 } 520 521 /** 522 * Detects a tablet (probably) running the Firefox OS. 523 * @return detection of a Firefox OS tablet 524 */ 525 public boolean detectFirefoxOSTablet() { 526 527 //First, let's make sure we're NOT on another major mobile OS. 528 if (detectIos() || detectAndroid() || detectSailfish()) { 529 return false; 530 } 531 532 if ((userAgent.indexOf(engineFirefox) != -1) && (userAgent.indexOf(deviceTablet) != -1)) { 533 return true; 534 } 535 536 return false; 537 } 538 539 /** 540 * Detects if the current device is an Internet-capable game console. 541 * Includes many handheld consoles. 542 * @return detection of any Game Console 543 */ 544 public boolean detectGameConsole() { 545 546 if (detectSonyPlaystation() || detectNintendo() || detectXbox()) { 547 return true; 548 } 549 return false; 550 } 551 552 /** 553 * Detects if the current device is a handheld gaming device with 554 * a touchscreen and modern iPhone-class browser. Includes the Playstation Vita. 555 * @return detection of a handheld gaming device 556 */ 557 public boolean detectGamingHandheld() { 558 559 if ((userAgent.indexOf(devicePlaystation) != -1) && (userAgent.indexOf(devicePlaystationVita) != -1)) { 560 return true; 561 } 562 return false; 563 } 564 565 /** 566 * Detects if the current browser is a 567 * Garmin Nuvifone. 568 * @return detection of a Garmin Nuvifone 569 */ 570 public boolean detectGarminNuvifone() { 571 572 if (userAgent.indexOf(deviceNuvifone) != -1) { 573 return true; 574 } 575 return false; 576 } 577 578 /** 579 * Detects if the current device is a GoogleTV. 580 * @return detection of GoogleTV 581 */ 582 public boolean detectGoogleTV() { 583 584 if (userAgent.indexOf(deviceGoogleTV) != -1) { 585 return true; 586 } 587 return false; 588 } 589 590 /** 591 * Detects *any* iOS device: iPhone, iPod Touch, iPad. 592 * @return detection of an Apple iOS device 593 */ 594 public boolean detectIos() { 595 596 if (detectIphoneOrIpod() || detectIpad()) { 597 return true; 598 } 599 return false; 600 } 601 602 /** 603 * Detects if the current device is an iPad tablet. 604 * @return detection of an iPad 605 */ 606 public boolean detectIpad() { 607 608 if ((userAgent.indexOf(deviceIpad) != -1) && detectWebkit()) { 609 return true; 610 } 611 return false; 612 } 613 614 /** 615 * Detects if the current device is an iPhone. 616 * @return detection of an iPhone 617 */ 618 public boolean detectIphone() { 619 620 // The iPad and iPod touch say they're an iPhone! So let's disambiguate. 621 if ((userAgent.indexOf(deviceIphone) != -1) && !detectIpad() && !detectIpod()) { 622 return true; 623 } 624 return false; 625 } 626 627 /** 628 * Detects if the current device is an iPhone or iPod Touch. 629 * @return detection of an iPhone or iPod Touch 630 */ 631 public boolean detectIphoneOrIpod() { 632 633 //We repeat the searches here because some iPods may report themselves as an iPhone, which would be okay. 634 if ((userAgent.indexOf(deviceIphone) != -1) || (userAgent.indexOf(deviceIpod) != -1)) { 635 return true; 636 } 637 return false; 638 } 639 640 /** 641 * Detects if the current device is an iPod Touch. 642 * @return detection of an iPod Touch 643 */ 644 public boolean detectIpod() { 645 646 if (userAgent.indexOf(deviceIpod) != -1) { 647 return true; 648 } 649 return false; 650 } 651 652 /** 653 * Detects if the current device is an Amazon Kindle (eInk devices only). 654 * Note: For the Kindle Fire, use the normal Android methods. 655 * @return detection of a Kindle 656 */ 657 public boolean detectKindle() { 658 659 if ((userAgent.indexOf(deviceKindle) != -1) && !detectAndroid()) { 660 return true; 661 } 662 return false; 663 } 664 665 /** 666 * Detects if the current device is on one of the Maemo-based Nokia Internet Tablets. 667 * @return detection of a Maemo OS tablet 668 */ 669 public boolean detectMaemoTablet() { 670 671 if (userAgent.indexOf(maemo) != -1) { 672 return true; 673 } else if ((userAgent.indexOf(linux) != -1) 674 && (userAgent.indexOf(deviceTablet) != -1) 675 && !detectWebOSTablet() 676 && !detectAndroid()) { 677 return true; 678 } 679 return false; 680 } 681 682 /** 683 * Detects a device running the Meego OS. 684 * @return detection of a Meego device 685 */ 686 public boolean detectMeego() { 687 688 if (userAgent.indexOf(deviceMeego) != -1) { 689 return true; 690 } 691 return false; 692 } 693 694 /** 695 * Detects a phone running the Meego OS. 696 * @return detection of a Meego phone 697 */ 698 public boolean detectMeegoPhone() { 699 700 if ((userAgent.indexOf(deviceMeego) != -1) && (userAgent.indexOf(mobi) != -1)) { 701 return true; 702 } 703 return false; 704 } 705 706 /** 707 * Detects if the current device supports MIDP, a mobile Java technology. 708 * @return detection of a MIDP mobile Java-capable device 709 */ 710 public boolean detectMidpCapable() { 711 712 if ((userAgent.indexOf(deviceMidp) != -1) || (httpAccept.indexOf(deviceMidp) != -1)) { 713 return true; 714 } 715 return false; 716 } 717 718 /** 719 * The longer and more thorough way to detect for a mobile device. 720 * Will probably detect most feature phones, 721 * smartphone-class devices, Internet Tablets, 722 * Internet-enabled game consoles, etc. 723 * This ought to catch a lot of the more obscure and older devices, also -- 724 * but no promises on thoroughness! 725 * @return detection of any mobile device using the more thorough method 726 */ 727 public boolean detectMobileLong() { 728 729 if (detectMobileQuick() || detectGameConsole()) { 730 return true; 731 } 732 733 if (detectDangerHiptop() || detectMaemoTablet() || detectSonyMylo() || detectArchos()) { 734 return true; 735 } 736 737 if ((userAgent.indexOf(devicePda) != -1) && (userAgent.indexOf(disUpdate) < 0)) //no index found 738 { 739 return true; 740 } 741 742 //Detect older phones from certain manufacturers and operators. 743 if ((userAgent.indexOf(uplink) != -1) 744 || (userAgent.indexOf(engineOpenWeb) != -1) 745 || (userAgent.indexOf(manuSamsung1) != -1) 746 || (userAgent.indexOf(manuSonyEricsson) != -1) 747 || (userAgent.indexOf(manuericsson) != -1) 748 || (userAgent.indexOf(svcDocomo) != -1) 749 || (userAgent.indexOf(svcKddi) != -1) 750 || (userAgent.indexOf(svcVodafone) != -1)) { 751 return true; 752 } 753 754 return false; 755 } 756 757 /** 758 * Detects if the current device is a mobile device. 759 * This method catches most of the popular modern devices. 760 * Excludes Apple iPads and other modern tablets. 761 * @return detection of any mobile device using the quicker method 762 */ 763 public boolean detectMobileQuick() { 764 765 //Let's exclude tablets 766 if (isTierTablet) { 767 return false; 768 } 769 //Most mobile browsing is done on smartphones 770 if (detectSmartphone()) { 771 return true; 772 } 773 774 //Catch-all for many mobile devices 775 if (userAgent.indexOf(mobile) != -1) { 776 return true; 777 } 778 779 if (detectOperaMobile()) { 780 return true; 781 } 782 783 //We also look for Kindle devices 784 if (detectKindle() || detectAmazonSilk()) { 785 return true; 786 } 787 788 if (detectWapWml() || detectMidpCapable() || detectBrewDevice()) { 789 return true; 790 } 791 792 if ((userAgent.indexOf(engineNetfront) != -1) || (userAgent.indexOf(engineUpBrowser) != -1)) { 793 return true; 794 } 795 796 return false; 797 } 798 799 /** 800 * Detects if the current device is a Nintendo game device. 801 * @return detection of Nintendo 802 */ 803 public boolean detectNintendo() { 804 805 if ((userAgent.indexOf(deviceNintendo) != -1) 806 || (userAgent.indexOf(deviceWii) != -1) 807 || (userAgent.indexOf(deviceNintendoDs) != -1)) { 808 return true; 809 } 810 return false; 811 } 812 813 /** 814 * Detects Opera Mobile or Opera Mini. 815 * @return detection of an Opera browser for a mobile device 816 */ 817 public boolean detectOperaMobile() { 818 819 if ((userAgent.indexOf(engineOpera) != -1) 820 && ((userAgent.indexOf(mini) != -1) || (userAgent.indexOf(mobi) != -1))) { 821 return true; 822 } 823 return false; 824 } 825 826 /** 827 * Detects if the current browser is on a PalmOS device. 828 * @return detection of a PalmOS device 829 */ 830 public boolean detectPalmOS() { 831 832 //Most devices nowadays report as 'Palm', but some older ones reported as Blazer or Xiino. 833 if ((userAgent.indexOf(devicePalm) != -1) 834 || (userAgent.indexOf(engineBlazer) != -1) 835 || (userAgent.indexOf(engineXiino) != -1)) { 836 //Make sure it's not WebOS first 837 if (detectPalmWebOS()) { 838 return false; 839 } else { 840 return true; 841 } 842 } 843 return false; 844 } 845 846 /** 847 * Detects if the current browser is on a Palm device 848 * running the new WebOS. 849 * @return detection of a Palm WebOS device 850 */ 851 public boolean detectPalmWebOS() { 852 853 if (userAgent.indexOf(deviceWebOS) != -1) { 854 return true; 855 } 856 return false; 857 } 858 859 /** 860 * Detects if the current browser is the Symbian S60 Open Source Browser. 861 * @return detection of Symbian S60 Browser 862 */ 863 public boolean detectS60OssBrowser() { 864 865 //First, test for WebKit, then make sure it's either Symbian or S60. 866 if (detectWebkit() && ((userAgent.indexOf(deviceSymbian) != -1) || (userAgent.indexOf(deviceS60) != -1))) { 867 return true; 868 } 869 return false; 870 } 871 872 /** 873 * Detects a device running the Sailfish OS. 874 * @return detection of a Sailfish device 875 */ 876 public boolean detectSailfish() { 877 878 if (userAgent.indexOf(deviceSailfish) != -1) { 879 return true; 880 } 881 return false; 882 } 883 884 /** 885 * Detects a phone running the Sailfish OS. 886 * @return detection of a Sailfish phone 887 */ 888 public boolean detectSailfishPhone() { 889 890 if (detectSailfish() && (userAgent.indexOf(mobile) != -1)) { 891 return true; 892 } 893 894 return false; 895 } 896 897 /** 898 * Check to see whether the device is any device 899 * in the 'smartphone' category. 900 * @return detection of a general smartphone device 901 */ 902 public boolean detectSmartphone() { 903 904 //Exclude duplicates from TierIphone 905 return (detectTierIphone() 906 || detectS60OssBrowser() 907 || detectSymbianOS() 908 || detectWindowsMobile() 909 || detectBlackBerry() 910 || detectMeegoPhone() 911 || detectPalmOS()); 912 } 913 914 /** 915 * Detects if the current browser is a Sony Mylo device. 916 * @return detection of a Sony Mylo device 917 */ 918 public boolean detectSonyMylo() { 919 920 if ((userAgent.indexOf(manuSony) != -1) 921 && ((userAgent.indexOf(qtembedded) != -1) || (userAgent.indexOf(mylocom2) != -1))) { 922 return true; 923 } 924 return false; 925 } 926 927 /** 928 * Detects if the current device is a Sony Playstation. 929 * @return detection of Sony Playstation 930 */ 931 public boolean detectSonyPlaystation() { 932 933 if (userAgent.indexOf(devicePlaystation) != -1) { 934 return true; 935 } 936 return false; 937 } 938 939 /** 940 * 941 * Detects if the current device is any Symbian OS-based device, 942 * including older S60, Series 70, Series 80, Series 90, and UIQ, 943 * or other browsers running on these devices. 944 * @return detection of SymbianOS 945 */ 946 public boolean detectSymbianOS() { 947 948 if ((userAgent.indexOf(deviceSymbian) != -1) 949 || (userAgent.indexOf(deviceS60) != -1) 950 || (userAgent.indexOf(deviceS70) != -1) 951 || (userAgent.indexOf(deviceS80) != -1) 952 || (userAgent.indexOf(deviceS90) != -1)) { 953 return true; 954 } 955 return false; 956 } 957 958 /** 959 * The quick way to detect for a tier of devices. 960 * This method detects for devices which can 961 * display iPhone-optimized web content. 962 * Includes iPhone, iPod Touch, Android, Windows Phone 7 and 8, BB10, WebOS, Playstation Vita, etc. 963 * @return detection of any device in the iPhone/Android/Windows Phone/BlackBerry/WebOS Tier 964 */ 965 public boolean detectTierIphone() { 966 967 if (detectIphoneOrIpod() 968 || detectAndroidPhone() 969 || detectWindowsPhone() 970 || detectBlackBerry10Phone() 971 || (detectBlackBerryWebKit() && detectBlackBerryTouch()) 972 || detectPalmWebOS() 973 || detectBada() 974 || detectTizen() 975 || detectFirefoxOSPhone() 976 || detectSailfishPhone() 977 || detectUbuntuPhone() 978 || detectGamingHandheld()) { 979 return true; 980 } 981 return false; 982 } 983 984 /** 985 * The quick way to detect for a tier of devices. 986 * This method detects for all other types of phones, 987 * but excludes the iPhone and RichCSS Tier devices. 988 * @return detection of a mobile device in the less capable tier 989 */ 990 public boolean detectTierOtherPhones() { 991 992 //Exclude devices in the other 2 categories 993 if (detectMobileLong() && !detectTierIphone() && !detectTierRichCss()) { 994 return true; 995 } 996 return false; 997 } 998 999 /** 1000 * The quick way to detect for a tier of devices. 1001 * This method detects for devices which are likely to be capable 1002 * of viewing CSS content optimized for the iPhone, 1003 * but may not necessarily support JavaScript. 1004 * Excludes all iPhone Tier devices. 1005 * @return detection of any device in the 'Rich CSS' Tier 1006 */ 1007 public boolean detectTierRichCss() { 1008 1009 boolean result = false; 1010 //The following devices are explicitly ok. 1011 //Note: 'High' BlackBerry devices ONLY 1012 if (detectMobileQuick()) { 1013 1014 //Exclude iPhone Tier and e-Ink Kindle devices. 1015 if (!detectTierIphone() && !detectKindle()) { 1016 1017 //The following devices are explicitly ok. 1018 //Note: 'High' BlackBerry devices ONLY 1019 //Older Windows 'Mobile' isn't good enough for iPhone Tier. 1020 if (detectWebkit() 1021 || detectS60OssBrowser() 1022 || detectBlackBerryHigh() 1023 || detectWindowsMobile() 1024 || (userAgent.indexOf(engineTelecaQ) != -1)) { 1025 result = true; 1026 } // if detectWebkit() 1027 } //if !detectTierIphone() 1028 } //if detectMobileQuick() 1029 return result; 1030 } 1031 1032 /** 1033 * The quick way to detect for a tier of devices. 1034 * This method detects for the new generation of 1035 * HTML 5 capable, larger screen tablets. 1036 * Includes iPad, Android (e.g., Xoom), BB Playbook, WebOS, etc. 1037 * @return detection of any device in the Tablet Tier 1038 */ 1039 public boolean detectTierTablet() { 1040 1041 if (detectIpad() 1042 || detectAndroidTablet() 1043 || detectBlackBerryTablet() 1044 || detectFirefoxOSTablet() 1045 || detectUbuntuTablet() 1046 || detectWebOSTablet()) { 1047 return true; 1048 } 1049 return false; 1050 } 1051 1052 /** 1053 * Detects a device running the Tizen smartphone OS. 1054 * @return detection of a Tizen device 1055 */ 1056 public boolean detectTizen() { 1057 1058 if ((userAgent.indexOf(deviceTizen) != -1) && (userAgent.indexOf(mobile) != -1)) { 1059 return true; 1060 } 1061 return false; 1062 } 1063 1064 /** 1065 * Detects if the current browser is on a Tizen smart TV. 1066 * @return detection of a Tizen smart TV 1067 */ 1068 public boolean detectTizenTV() { 1069 1070 if ((userAgent.indexOf(deviceTizen) != -1) && (userAgent.indexOf(smartTV1) != -1)) { 1071 return true; 1072 } 1073 return false; 1074 } 1075 1076 /** 1077 * Detects a mobile device running the Ubuntu Mobile OS. 1078 * @return detection of an Ubuntu Mobile OS mobile device 1079 */ 1080 public boolean detectUbuntu() { 1081 1082 if (detectUbuntuPhone() || detectUbuntuTablet()) { 1083 return true; 1084 } 1085 1086 return false; 1087 } 1088 1089 /** 1090 * Detects a phone running the Ubuntu Mobile OS. 1091 * @return detection of an Ubuntu Mobile OS phone 1092 */ 1093 public boolean detectUbuntuPhone() { 1094 1095 if ((userAgent.indexOf(deviceUbuntu) != -1) && (userAgent.indexOf(mobile) != -1)) { 1096 return true; 1097 } 1098 1099 return false; 1100 } 1101 1102 /** 1103 * Detects a tablet running the Ubuntu Mobile OS. 1104 * @return detection of an Ubuntu Mobile OS tablet 1105 */ 1106 public boolean detectUbuntuTablet() { 1107 1108 if ((userAgent.indexOf(deviceUbuntu) != -1) && (userAgent.indexOf(deviceTablet) != -1)) { 1109 return true; 1110 } 1111 1112 return false; 1113 } 1114 1115 /** 1116 * Detects whether the device supports WAP or WML. 1117 * @return detection of a WAP- or WML-capable device 1118 */ 1119 public boolean detectWapWml() { 1120 1121 if ((httpAccept.indexOf(vndwap) != -1) || (httpAccept.indexOf(wml) != -1)) { 1122 return true; 1123 } 1124 return false; 1125 } 1126 1127 /** 1128 * Detects if the current browser is based on WebKit. 1129 * @return detection of a WebKit browser 1130 */ 1131 public boolean detectWebkit() { 1132 1133 if (userAgent.indexOf(engineWebKit) != -1) { 1134 return true; 1135 } 1136 return false; 1137 } 1138 1139 /** 1140 * Detects if the current browser is on an HP tablet running WebOS. 1141 * @return detection of an HP WebOS tablet 1142 */ 1143 public boolean detectWebOSTablet() { 1144 1145 if ((userAgent.indexOf(deviceWebOShp) != -1) && (userAgent.indexOf(deviceTablet) != -1)) { 1146 return true; 1147 } 1148 return false; 1149 } 1150 1151 /** 1152 * Detects if the current browser is on a WebOS smart TV. 1153 * @return detection of a WebOS smart TV 1154 */ 1155 public boolean detectWebOSTV() { 1156 1157 if ((userAgent.indexOf(deviceWebOStv) != -1) && (userAgent.indexOf(smartTV2) != -1)) { 1158 return true; 1159 } 1160 return false; 1161 } 1162 1163 /** 1164 * Detects if the current browser is a Windows Mobile device. 1165 * Excludes Windows Phone 7.x and 8 devices. 1166 * Focuses on Windows Mobile 6.xx and earlier. 1167 * @return detection of Windows Mobile 1168 */ 1169 public boolean detectWindowsMobile() { 1170 1171 if (detectWindowsPhone()) { 1172 return false; 1173 } 1174 //Most devices use 'Windows CE', but some report 'iemobile' 1175 // and some older ones report as 'PIE' for Pocket IE. 1176 // We also look for instances of HTC and Windows for many of their WinMo devices. 1177 if ((userAgent.indexOf(deviceWinMob) != -1) 1178 || (userAgent.indexOf(deviceWinMob) != -1) 1179 || (userAgent.indexOf(deviceIeMob) != -1) 1180 || (userAgent.indexOf(enginePie) != -1) 1181 || ((userAgent.indexOf(manuHtc) != -1) && (userAgent.indexOf(deviceWindows) != -1)) 1182 || (detectWapWml() && (userAgent.indexOf(deviceWindows) != -1))) { 1183 return true; 1184 } 1185 1186 //Test for Windows Mobile PPC but not old Macintosh PowerPC. 1187 if ((userAgent.indexOf(devicePpc) != -1) && !(userAgent.indexOf(deviceMacPpc) != -1)) { 1188 return true; 1189 } 1190 1191 return false; 1192 } 1193 1194 /** 1195 * Detects if the current browser is a Windows Phone 7.x, 8, or 10 device 1196 * @return detection of Windows Phone 7.x OR 8 1197 */ 1198 public boolean detectWindowsPhone() { 1199 1200 if (detectWindowsPhone7() || detectWindowsPhone8() || detectWindowsPhone10()) { 1201 return true; 1202 } 1203 return false; 1204 } 1205 1206 /** 1207 * Detects a Windows Phone 10 device (in mobile browsing mode). 1208 * @return detection of Windows Phone 10 1209 */ 1210 public boolean detectWindowsPhone10() { 1211 1212 if (userAgent.indexOf(deviceWinPhone10) != -1) { 1213 return true; 1214 } 1215 return false; 1216 } 1217 1218 /** 1219 * Detects a Windows Phone 7 device (in mobile browsing mode). 1220 * @return detection of Windows Phone 7 1221 */ 1222 public boolean detectWindowsPhone7() { 1223 1224 if (userAgent.indexOf(deviceWinPhone7) != -1) { 1225 return true; 1226 } 1227 return false; 1228 } 1229 1230 /** 1231 * Detects a Windows Phone 8 device (in mobile browsing mode). 1232 * @return detection of Windows Phone 8 1233 */ 1234 public boolean detectWindowsPhone8() { 1235 1236 if (userAgent.indexOf(deviceWinPhone8) != -1) { 1237 return true; 1238 } 1239 return false; 1240 } 1241 1242 /** 1243 * Detects if the current device is a Microsoft Xbox. 1244 * @return detection of Xbox 1245 */ 1246 public boolean detectXbox() { 1247 1248 if (userAgent.indexOf(deviceXbox) != -1) { 1249 return true; 1250 } 1251 return false; 1252 } 1253 1254 /** 1255 * Return the lower case HTTP_ACCEPT 1256 * @return httpAccept 1257 */ 1258 public String getHttpAccept() { 1259 1260 return httpAccept; 1261 } 1262 1263 //***************************** 1264 // Device Classes 1265 //***************************** 1266 1267 /** 1268 * Return whether the device is an Iphone or iPod Touch 1269 * @return isIphone 1270 */ 1271 public boolean getIsIphone() { 1272 1273 return isIphone; 1274 } 1275 1276 /** 1277 * Return whether the device is a generic, less-capable mobile device. 1278 * @return isTierGenericMobile 1279 */ 1280 public boolean getIsTierGenericMobile() { 1281 1282 return isTierGenericMobile; 1283 } 1284 1285 /** 1286 * Return whether the device is in the Iphone Tier. 1287 * @return isTierIphone 1288 */ 1289 public boolean getIsTierIphone() { 1290 1291 return isTierIphone; 1292 } 1293 1294 //***************************** 1295 // For Mobile Web Site Design 1296 //***************************** 1297 1298 /** 1299 * Return whether the device is in the 'Rich CSS' tier of mobile devices. 1300 * @return isTierRichCss 1301 */ 1302 public boolean getIsTierRichCss() { 1303 1304 return isTierRichCss; 1305 } 1306 1307 /** 1308 * Return whether the device is in the Tablet Tier. 1309 * @return isTierTablet 1310 */ 1311 public boolean getIsTierTablet() { 1312 1313 return isTierTablet; 1314 } 1315 1316 /** 1317 * Return the lower case HTTP_USER_AGENT 1318 * @return userAgent 1319 */ 1320 public String getUserAgent() { 1321 1322 return userAgent; 1323 } 1324 1325 /** 1326 * Initialize Key Stored Values. 1327 */ 1328 public void initDeviceScan() { 1329 1330 //Save these properties to speed processing 1331 this.isWebkit = detectWebkit(); 1332 this.isIphone = detectIphone(); 1333 this.isAndroid = detectAndroid(); 1334 this.isAndroidPhone = detectAndroidPhone(); 1335 1336 //Generally, these tiers are the most useful for web development 1337 this.isMobilePhone = detectMobileQuick(); 1338 this.isTierTablet = detectTierTablet(); 1339 this.isTierIphone = detectTierIphone(); 1340 1341 //Optional: Comment these out if you NEVER use them 1342 this.isTierRichCss = detectTierRichCss(); 1343 this.isTierGenericMobile = detectTierOtherPhones(); 1344 1345 this.initCompleted = true; 1346 } 1347}