ChatGPT解决这个技术问题 Extra ChatGPT

通过 javascript 检测 ipad/iphone webview

如果网站在 iPad 的 Safari 内或应用程序 WebView 内运行,有没有办法用 JavaScript 检测?

这仅适用于 iOS 设备吗?

T
ThinkingStiff

这使用了 window.navigator.userAgentwindow.navigator.standalone 的组合。它可以区分与 iOS Web 应用程序相关的所有四种状态:safari(浏览器)、独立(全屏)、uiwebview 和非 iOS。

演示:http://jsfiddle.net/ThinkingStiff/6qrbn/

var standalone = window.navigator.standalone,
    userAgent = window.navigator.userAgent.toLowerCase(),
    safari = /safari/.test( userAgent ),
    ios = /iphone|ipod|ipad/.test( userAgent );

if( ios ) {
    if ( !standalone && safari ) {
        //browser
    } else if ( standalone && !safari ) {
        //standalone
    } else if ( !standalone && !safari ) {
        //uiwebview
    };
} else {
    //not iOS
};

chrome 在 userAgent 中有 Safari。它在要求 .ics 文件的 webcal:// 协议方面表现不同
@svlada 你能提供更多信息吗?您的设备及其 iOS 版本是什么?
Safari 和 Telegram 都在用户代理中包含“safari”,所以这不起作用
D
David Berry

用户代理

在 UIWebView 中运行

Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/98176

在 iPad 上的 Safari 中运行

Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B176 Safari/7534.48.3

在 Mac OS X 上的 Safari 中运行

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.5 Safari/534.55.3

在 Mac OS X 上的 Chrome 中运行

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.151 Safari/535.19

在 Mac OS X 上的 FireFox 中运行

Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:11.0) Gecko/20100101 Firefox/11.0

检测码

var is_uiwebview = /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent);
var is_safari_or_uiwebview = /(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent);

真的。我不知道为什么我首先自己查看了两个用户代理。感谢您的回答 :)
不适用于 iPhone 5s/iOS 7,因为 UIWebView 和 Safari 在其用户代理中都有 Safari
@Razor你是对的。在最新的 iOS 中,针对 Version 而不是 Safari 的测试对我有用。
@unceus 您能否准确概述一下您对 Version 的含义?您是否将 var is_uiwebview 行中的 Safari 替换为 Version
@HenrikPetterson 关于用户代理字符串,比较上面的前两个用户代理字符串(UIWebView 和 iPad 上的 Safari),UIWebView 字符串包含“版本”,而 ipad 则没有。您修改正则表达式的目标尚不清楚,听起来您可能正在寻求帮助来编写一个。
N
Nicolas S

我认为您可以只使用User-Agent

更新

使用 iPhone Safari 浏览的页面

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7

我将尝试使用 UIWebView

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Mobile/8B117

不同之处在于 Safari 显示的是 Safari/6531.22.7

解决方案

var isSafari = navigator.userAgent.match(/Safari/i) != null;

是的,但是您是否知道在 User-Agent 中是否有特定的字符串或可以检测 UIWebView 的东西?到目前为止我什么都找不到...
这仅适用于 iOS 设备吗?
Nicolas 目前的数字会有所不同,因为 Safari 和 UIWebView(以及“独立”——即主屏幕——网络应用程序)使用不同的引擎。这在 iOS 5 中发生了变化。
我不是指数字,我的意思是 UIWebView 中缺少 Safari/..... 本身
@Nicolas:非常正确,抱歉我没注意。我想知道是否有人可以确认iOS5中是否仍然如此?
A
Amir Khorsandi

我已经尝试了所有这些解决方案,但在我的情况下都不起作用,
我将在 Telegram 中检测 Webview。我认为它使用 SFSafariViewController
我注意到 Safari 应用程序将所有电话样式文本更改为带有“tel:”前缀的链接,但 webview 没有。
所以,我使用了它。
在这里测试它: jsfiddle

<!DOCTYPE html>
<html>
<head></head>
<body>
<ul id="phone" style="opacity:0">
    <li>111-111-1111</li>
</ul>
</body>
</html>

<script>

    var html = document.getElementById("phone").innerHTML;

    if (navigator.platform.substr(0,2) === 'iP') {

        if (html.indexOf('tel:') == -1)
            alert('not safari browser');
        else
            alert('safari browser');
    }
    else
        alert('not iOS');
</script>

您不应该依赖这种技巧,因为用户或任何其他开发人员可以禁用电话检测。
@БодровАндрей 我同意你的观点,但这是我能找到的唯一方法,我希望苹果将来为此提供不同的用户代理
请注意这在 iOS 13 上是 borken,因为如果使用桌面模式,那么 navigator.platform === 'MacIntel'。这尤其会影响 iPadOS 13 Mobile Safari,因为它默认使用桌面模式。
@robocat 你是对的。它在 iOS 13 iPad 中坏了,我现在没有解决方案。你能在这里帮我解决相关问题吗stackoverflow.com/questions/58344491/…
T
ThinkingStiff

是的:

// is this an IPad ?
var isiPad = (navigator.userAgent.match(/iPad/i) != null);

// is this an iPhone ?
var isiPhone = (navigator.userAgent.match(/iPhone/i) != null);

// is this an iPod ?
var isiPod = (navigator.userAgent.match(/iPod/i) != null);

这也将匹配 Safari 浏览器,不仅是 WebView。
@ThinkingStuff - 你能帮我区分 Mac OS(桌面浏览器)和 iPad Safari 浏览器 - stackoverflow.com/questions/58344491/…
B
Boris Chumichev

请注意,此方法不适用于 iOS 10 及更早版本。

在 2018 年春季,没有一个建议的方法对我有用,所以我想出了一种新方法(不是基于 userAgent):

const hasValidDocumentElementRatio =
  [ 320 / 454 // 5, SE
  , 375 / 553 // 6, 7, 8
  , 414 / 622 // 6, 7, 8 Plus
  , 375 / 812 // X
  , 414 / 896 // Xs, Xr
  ].some(ratio =>
    ratio === document.documentElement.clientWidth / 
      document.documentElement.clientHeight
  )

const hasSafariInUA = /Safari/.test(navigator.userAgent)

const isiOSSafari = hasSafariInUA && hasValidDocumentElementRatio  // <- this one is set to false for webviews

https://gist.github.com/BorisChumichev/7c0ea033daf33da73306a396ffa174d1

欢迎您也为 iPad 设备扩展代码,我认为它应该可以解决问题。

适用于 Telegram、Facebook、VK 网页浏览。


iPhone X 为 375 / 812,也是新的:iPhone Xs Max/Xr 为 414 / 896
对于 iPhone 12,横向模式为 390 / 664 & 750 / 307
e
eosphere

Neoneye 的解决方案不再起作用(见评论)并且可以简化。另一方面,在 UA 中仅测试“Safari”的地址比 ios 手持设备要多得多。

这是我正在使用的测试:

var is_ios = /(iPhone|iPod|iPad).*AppleWebKit.*Safari/i.test(navigator.userAgent);

M
Milen Yordanov

现在是 2022 年,Safari 版本是 15.4。以上解决方案都不适合我。 iOS 上有两个 webview 类:WKWebView 和 SFSafariViewController。 SFSafariViewController 与 Safari 具有相同的 userAgent。我想出的解决方案依赖于在 Mobile Safari 上如何处理 height: 100vh。 100vh 是设备屏幕高度,而不是文档可见高度。

有关更多信息,请参阅:

https://developers.google.com/web/updates/2016/12/url-bar-resizing

https://bugs.webkit.org/show_bug.cgi?id=141832

https://github.com/bokand/URLBarSizing

因此,在 iOS 上,这样的功能会检测 WebView 模式。

function isWebView()
{
    const htmlEl = document.getElementsByTagName('html')[0];
    const bodyEl = document.getElementsByTagName('body')[0];

    const oldHtmlHeight = htmlEl.style.height;
    const oldBodyHeight = bodyEl.style.height;

    htmlEl.style.height = "100vh";
    bodyEl.style.height = "100%";

    const webViewMode = document.documentElement.clientHeight === document.documentElement.scrollHeight;

    // restore height
    htmlEl.style.height = oldHtmlHeight;
    bodyEl.style.height = oldBodyHeight;

    return webViewMode;
}


我试过但没有用。我想要一个例子
这是一个演示链接,尝试从 twitter 移动应用打开链接以在 webview 中打开,但我在 webview 模式下得到错误codesandbox.io/s/reverent-violet-n3jo8u
M
Mahmoud D. Alghraibeh

尝试使用 IOS 13

      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)

P
Preston

我知道此代码将检查是否从添加到主屏幕的图标访问它:

if (window.navigator.standalone == true) {
//not in safari
}

但我不确定它在 UIWebView 中会如何反应。我能想到的唯一其他解决方案是获取用户代理或使用 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 并将您正在访问的页面的查询字符串替换为页面用来识别它正在从 Web 视图访问的内容。


谢谢,我正在使用该代码,但需要更多控制。它似乎只检测到独立模式,并认为其余的是 Safari。
j
jiku

建议使用 Modernizr,并检查 indexeddb,如 this。您可以使用用户代理配置(设备、操作系统、浏览器等)进行交叉检查,但似乎更推荐使用纯特征检测。


听起来像是一个计划,但您会测试哪些功能? indexeddb 是 ie、chrome、firefox 等的一部分
C
CatalinBerta

上次我需要这个(只是为了 WebView 目的),我使用了这个检查:

function isIOS() {
     return !/safari/.test( window.navigator.userAgent.toLowerCase()) || navigator.platform === 'iOS' || navigator.platform === 'iPhone';
}

这在 iOS13 桌面模式(平台不再设置为 iPad 或 iPhone)和 iPod touch(平台可以是“iPod”或“iPod touch”)上被打破。
V
Vijay Dhanvai

我找到了一个简单的解决方案来检测 iPhone 或 iPad。这对我来说很好。

var is_iPad = navigator.userAgent.match(/iPad/i) != null;
var is_iPhone = navigator.userAgent.match(/iPhone/i) != null;
    if(is_iPad || is_iPhone == true){
        //perform your action
    }

v
vinni

Working 15.02.19

在 iOS 上检测网络视图的另一种解决方案是检查 navigator.mediaDevices 的支持/存在。

if (navigator.mediaDevices) {
    alert('has mediaDevices');
} else {
    alert('has no mediaDevices');
}

在我的情况下,我不需要捕获所有 webview,但是那些不支持摄像头/麦克风输入的 webview(提醒:警报不会在 Webview 中触发,因此请确保在 dom 中更改某些内容以进行调试)


Safari 和 Telegram 都有 mediaDevices
@Chris 你说 Telegram 是什么意思?单击消息中的链接时打开的内置浏览器?它不是 webview,它是一个应用内浏览器,类似于常规 Safari,但与真正的 webview 非常不同。
似乎这段代码是当今最可靠的。但请记住,HTTP 页面上没有 navigator.mediaDevices,因此您不能在 HTTP 页面上使用此方法。
C
Community

我不认为您可以在客户端 Javascript 中使用任何特定的东西,但是如果您可以控制原始 UIWebView 可以做什么,您可能需要考虑使用它生成的用户代理字符串,并在您的客户端Javascript呢?我知道有点 hack,但是,嘿……这个问题可能会为调整用户代理提供一些指导:

Change User Agent in UIWebView (iPhone SDK)


谢谢,本。不幸的是,我无法控制应用程序的 UIWebView 用户代理。
A
Amitg2k12

@ Sod,嗯,我没有答案,但我不相信你为什么要检查,因为,浏览器引擎是否它的 safari(浏览器)或应用程序将与它的 Webkit 相同,是的应用程序可以配置浏览器引擎功能,如, 应用程序是否要运行 JS 或 Display Image 等...

我相信,您必须检查浏览器是否支持 Flash 或浏览器是否显示图像的某些属性,或者您可能想检查屏幕大小,


你可以在评论中讨论这个。反正有很多情况要检查 wevbview