【问题标题】:How to detect device name in Safari on iOS 13 while it doesn't show the correct user agent?如何在 iOS 13 上的 Safari 中检测设备名称而不显示正确的用户代理?
【发布时间】:2020-01-20 23:41:09
【问题描述】:

Apple 的 iOS 13 发布后,我意识到 iPad iOS 13 上的 Safari 中的 window.navigator.userAgent 与 MacOS 上的相同。像这样的:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15

如您所见,这是一个错误的 iPad 用户代理,无法检测当前设备是否为 iDevice。


经过初步研究,我找到了解决方法:

转到设置 -> Safari -> 请求桌面网站 -> 所有网站。您注意到“所有网站”默认启用。如果您禁用它并获取 window.navigator.userAgent,则现在会显示正确的用户代理。

但我不能要求每个用户为每个设备进行此设置更改。所以我试图找到另一种方法并最终编写了以下代码来检查它是否是 Safari、macOS 和触摸屏,那么该设备应该是苹果移动设备,但我想知道是有更好的建议/方法来检测 Safari iOS 13 中的正确设备名称吗?

detectOs = function(){
   //returns OS name, like "mac"
};

//is Safari on an apple touch-screen device
isSafariInIdevice = function(){
   if (/Safari[\/\s](\d+\.\d+)/.test(windows.navigator.userAgent)) {
      return 'ontouchstart' in window && detectOs() === "mac";      
   }
   return false;
};

【问题讨论】:

  • 我遇到了同样的问题,但我需要检查服务器端,以便我可以在 Safari iOS13 上显示移动端菜单而不是完整的网站菜单。你能帮我解决这个问题吗? stackoverflow.com/questions/58344491/…
  • 为什么你需要知道这个?通常浏览器嗅探是一个坏主意。相反,您应该编写您的应用程序,以便它可以平等地在所有浏览器上运行。如果您需要区分浏览器的功能,请查看feature detection
  • OP,您能否将@kikiwora 的答案标记为已接受
  • OP,如果它确实解决了您的问题,您能否将@kikiwora 的答案标记为已接受?如果没有,如果您在此解决方案中遇到其他问题,请告诉我们。

标签: javascript ios safari user-agent ios13


【解决方案1】:

确实,虽然“设置”中的选项更改对用户来说可能是一个很好的解决方案,但作为开发人员,您不能依赖它。这就像要求用户不要使用暗模式一样奇怪,因为您的应用不支持它,而不是使用 plist 选择退出它。

对我来说,现在最简单的检测 iOS / iPad OS 设备的方法:

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

第一个条件是老式的并且适用于以前的版本, 而第二个条件适用于 iPad OS 13,它现在将自己标识为:

"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko)"

我所知道的所有平台检测器都没有(目前)检测到移动设备和桌面设备。

因此,由于 iPad OS 现在自称为 Macintosh,但真正的 Mac 不支持多点触控,因此该解决方案非常适合检测 iPad OS 设备,因为它是唯一存在的多点触控“Macintosh”设备。

附言 此外,您可能希望增加此检查以防止 IE 被检测为 iOS 设备

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

【讨论】:

  • 感谢这对客户端有用。您能否帮助如何在页面呈现时在服务器端检测剃刀语法。严重卡住了这个问题。 stackoverflow.com/questions/58344491/…
  • 我不精通剃须刀,对不起??‍♂️另外,我认为这在服务器端是不可能的,因为 iPad 将 Macintosh 标头发送到服务器 - iPad 现在意味着像桌面一样工作在网络中,我们不应该干预这种行为
  • 这个解决方案最初是为 Safari 设计的。奇怪的是,Mozilla 网站将此 JS 方法列为 Safari 不支持。它绝对适用于我所有的 Apple 设备(笔记本电脑、平板电脑和手机),但事实上,从长期使用的角度来看,这种方法的缺点是非常脆弱的。尤其是当支持触控的 Mac 可用时。问题是,正如我所说,新的 Safari 本来就是这样的——它被设计为被检测为桌面,为用户提供更多功能,因为现代网站通常不是功能强大的移动版本,而是迫使用户使用它们.
  • 感谢您的解决方案。这解决了我需要它的问题。虽然这不是最好的长期方案,但它是一个很好的创可贴解决方案,直到 Apple 推出触摸屏电脑,或者他们把他们的废话放在一起并正确命名他们的设备!
  • ⚠️ 只是作为一个通知 - 此代码可能很快就会过时,因为现在我们有一个基于 Apple Silicone 的 Mac 并且在 App Store 动画中发现了关于基于触控的 Mac 的提示,甚至公开展示了一段时间。
【解决方案2】:
const isIOS = !!(/iPad|iPhone|iPod/.test(navigator.platform)
  || (navigator.platform === "MacIntel" && typeof navigator.standalone !== "undefined"))

作为已接受答案的替代方案,我发现您可以使用 navigator.standalone 参数。它是非标准的,目前仅在 iOS Safari 上使用:

Navigator.standalone

返回一个布尔值,指示浏览器是否在独立模式下运行。仅适用于 Apple 的 iOS Safari。

当与navigator.platform === "MacIntel" 结合使用时,iPad 是唯一定义此属性的设备,因此typeof navigator.standalone !== "undefined" 会过滤掉运行 Safari(触摸屏与否)的 Mac。

【讨论】:

  • 不应该是isIpadSafari = 吗?
  • @kofifus 平台字符串中 iPad//iPhone/iPod 的 OR 条件测试的第一部分。第二部分是 iOS 13 iPad,所以它不只是在寻找运行 Safari 的 iPad
【解决方案3】:
     function mobileDetect() {


    var agent = window.navigator.userAgent;
    var d = document;
    var e = d.documentElement;
    var g = d.getElementsByTagName('body')[0];
    var deviceWidth = window.innerWidth || e.clientWidth || g.clientWidth;

    // Chrome
    IsChromeApp = window.chrome && chrome.app && chrome.app.runtime;

    // iPhone
    IsIPhone = agent.match(/iPhone/i) != null;

    // iPad up to IOS12
    IsIPad = (agent.match(/iPad/i) != null) || ((agent.match(/iPhone/i) != null) && (deviceWidth > 750)); // iPadPro when run with no launch screen can have error in userAgent reporting as an iPhone rather than an iPad. iPadPro width portrait 768, iPhone6 plus 414x736 but would probably always report 414 on app startup

    if (IsIPad) IsIPhone = false;

    // iPad from IOS13
    var macApp = agent.match(/Macintosh/i) != null;
    if (macApp) {
        // 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) IsIPad = true;
                }
                ;
            }
            ;
        }
        ;
    }
    ;

    // IOS
    IsIOSApp = IsIPad || IsIPhone;

    // Android
    IsAndroid = agent.match(/Android/i) != null;
    IsAndroidPhone = IsAndroid && deviceWidth <= 960;
    IsAndroidTablet = IsAndroid && !IsAndroidPhone;



    message = ""


    if (IsIPhone) {

        message = "Device is IsIPhone"


    }
    else if (IsIPad) {

        message = "Device is ipad"

    } else if (IsAndroidTablet || IsAndroidPhone || IsAndroid) {

        message = "Device is Android"


    } else {

        message = "Device is Mac ||  Windows Desktop"

    }


    return {

        message: message,

        isTrue: IsIOSApp || IsAndroid || IsAndroidTablet || IsAndroidPhone

    }

}



const checkMobile = mobileDetect()

alert(checkMobile.message + "  =====>  " + checkMobile.isTrue)
shareeditdeleteflag

【讨论】:

  • 这将检测到 iPhone 也是 iPad,因为 deviceWidth > 750。
  • @RogerFar 我认为与将触摸屏 iBook 或 iMac 归类为移动设备相比,这不是一种牺牲。似乎人们在这个问题上完全迷失了方向,因为 Safari 现在可以说谎了,解决这个问题的唯一方法是测试一些像 sn-p 这样的功能。如果您愿意,可以添加更多代码来测试宽度并根据需要进一步完善它。
【解决方案4】:
UIWebView *webView = [[UIWebView alloc] init];
NSString *command =[NSString stringWithFormat:@"navigator.userAgent"];
NSString *customUserAgent = [webView stringByEvaluatingJavaScriptFromString:command];
[(WKWebView *)_webView setCustomUserAgent:customUserAgent];

【讨论】:

  • 请为您的回答提供一些解释。
  • 语言完全错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-26
  • 1970-01-01
相关资源
最近更新 更多