8

I am able to detect iPadAir2 device running on iOS 11.4 using Request.Browser.IsMobileDevice and it gives me UserAgent information saying its an iPad: enter image description here

When I do same for iPadAir2 running on iOS 13.0.1 its not giving me iPad keyword anymore: enter image description here

how do I detect its an ipad and ruuning a safari browser?

I need this to detect iPad in Razor .chtml page so I can show different Menu for my website.

I found this solution from here How to detect device name in Safari on iOS 13 while it doesn't show the correct user agent?

let isIOS = /iPad|iPhone|iPod/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)

How to use this variable in razor to change website menu ?

newdeveloper
  • 1,401
  • 3
  • 17
  • 43
  • Generally browser sniffing is a bad idea. Instead you should be writing your application so that it works on all browsers equally. Why do you need to display a different menu for a specfic browser? If you need to disinguish between abilities of browsers then look into [feature detection](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Feature_detection). – RoToRa Oct 15 '19 at 08:54
  • Have you found any solution? If so please answer your own question. – anbuj Jan 02 '20 at 09:59
  • 2
    @anbuj I haven't actually. we just changed some expectations for such devices. sorry could not help. – newdeveloper Jan 02 '20 at 16:49

1 Answers1

4

Before iOS 13 (a.k.a. before Safari started to "lie" by default) we could have had a solution like this: https://stackoverflow.com/a/32947785/292502. Now that iPad Safari mimics desktop user agent by default puts the developer in a hard spot unless the user can be expected to switch that Safari behavior off (often times the user does not even know if a device is Android tablet or an iPad).

The ASP.NET or C# versions of the Detect Mobile Browsers script also operate in C# land and you'd need to access other fields of the navigator JavaScript object.

So we have to resort to move this whole detection code into one of your JavaScript files. Then you'd start off of the JavaScript or jQuery version Detect Mobile Browsers script. I transformed that into a function which just returns the boolean verdict.

You'd add the extras what others advise, but here we'd need to make a choice: regarding what is the real reason behind we'd like to detect the device's type.

  1. If we are OK that touch screen iBooks or iMacs are considered mobile, then we can resort to a simple (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1) type extra approach. with the M1 Macs this criteria would not work because those are ARM based. It depends on what the navigator say about them. This would work if our main reason is related to touch screen navigation.
  2. If we rather focus on the mobile/tablet because of the form factor and not just the touch capability, then the first approach is not adequate. We'd need to have some extra test which would reveal the "lying" Safari. The downvoted https://stackoverflow.com/a/59408181/292502 shows one possibility for that. There's no way to reveal a lying Safari other then test for some custom features which busts it. The downside of this solution is that it can be brittle if the tested capability changes in the future.

My solution would be something along the line of:

function detectmobilebrowser() {
  var userAgent = navigator.userAgent || navigator.vendor || window.opera;
  if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|android|playbook|silk|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(userAgent) ||
      /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4)))
    return true;

  // Lying iOS13 iPad
  if (userAgent.match(/Macintosh/i) !== null) {
    // need to distinguish between Macbook and iPad
    var canvas = document.createElement("canvas");
    if (canvas !== null) {
      var context = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
      if (context) {
        var info = context.getExtension("WEBGL_debug_renderer_info");
        if (info) {
          var renderer = context.getParameter(info.UNMASKED_RENDERER_WEBGL);
          if (renderer.indexOf("Apple") !== -1)
            return true;
        }
      }
    }
  }

  return false;
}

That first part is a modified version of the jQuery Detect Mobile Browser. The modification is the "non lying" iPad support by adding the ad into |ip(hone|od|ad). Then I add the lying iPad detection. This code may need more modification and more testing! Then you could call the detectmobilebrowser() in the appropriate places and act on it. As this is moved to JavaScript land this is not Razor solution any more, but this is how you can go about this right now in my opinion.


For my own application as well you can test this code here:

Csaba Toth
  • 10,021
  • 5
  • 75
  • 121
  • I need someone with an iBook, iMac, touchscreen iBook / iMac to test it – Csaba Toth Mar 05 '20 at 22:33
  • Unfortunately, this approach doesn't work for M1 notebooks. Checking "navigator.maxTouchPoints > 1" somewhere in the code may help. – Zafer Jan 20 '21 at 14:15
  • @Zafer So you mean that M1 notebooks would test true for the "WEBGL_debug_renderer_info" type extra check? Then the question is: are there any M1 Macbooks which are touch capable? Thanks for bringing attention to that! – Csaba Toth Jul 05 '21 at 22:45
  • @Zafer https://github.com/CsabaConsulting/DetectMobileTest/issues/1 – Csaba Toth Jul 05 '21 at 22:50
  • 1
    As far as I know M1 macbooks are not touch capable. So, this sort of hack is OK for now. – Zafer Jul 12 '21 at 12:47
  • @Zafer could you test what the navigator.platform displays? I added it to the website on https://csabaconsulting.github.io/DetectMobileTest/ along with the max touch points – Csaba Toth Jul 12 '21 at 17:11
  • 1
    I updated the repo, so it should work now. Let me know if you run into any anomaly – Csaba Toth Nov 12 '21 at 08:28