通过javascript检测ipad / iphone Webview


91

如果网站在ipad Safari或应用程序WebView中运行,是否可以通过JavaScript进行区别?


这仅适用于iOS设备吗?
Nicolas S

Answers:


79

这里使用的组合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 Safari在userAgent中具有。webcal://对于.ics文件的协议要求,它的行为有所不同
neaumusic 2015年

@svlada您可以提供更多信息吗?您的设备及其iOS版本是什么?
sonlexqt

78

用户代理

在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);

真。我不知道为什么我首先只是自己看两个用户代理。感谢您的回答:)
草皮

4
UIWebView无法Safari在iPhone 5s / iOS 7上运行,因为Safari和Safari都在其用户代理中
Razor 2014年

@剃刀你是对的。在最新的iOS中,针对进行测试而Version不是Safari对我有用。
unceus 2014年

1
@unceus能否请您概述一下您的意思Version?你替换SafariVersionvar is_uiwebview线?
亨里克·佩特森

@HenrikPetterson关于用户代理字符串,比较上面的前两个用户代理字符串(UIWebView和iPad上的Safari),UIWebView字符串包含“版本”,而ipad则没有。修改正则表达式的目标尚不清楚,听起来您可能正在寻找编写正则表达式的帮助。
Unceus '16

10

我认为您可以使用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?到目前为止,我什么都找不到...
Adam Tal

这仅适用于iOS设备吗?
Nicolas S

Nicolas目前的数字会有所不同因为Safari和UIWebView(以及“独立”(即主屏幕)Web应用程序)使用不同的引擎。这在iOS 5中有所更改
本钟

我不是指数字,Safari/.....而是指UIWebView中本身不存在
Nicolas S

@Nicolas:是的,很抱歉,我没有注意。我想知道是否有人可以确认iOS5是否仍然如此?

7

是的:

// 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);

11
这也将匹配Safari浏览器,不仅是WebView。
彼得·佩勒

@ThinkingStuff -你能帮助我帮助diiferentiate的Mac OS(桌面浏览器)和iPad的Safari浏览器之间- stackoverflow.com/questions/58344491/...
newdeveloper

5

我已经尝试了所有这些解决方案,但在我的情况下不起作用,
我打算在Webview中检测Telegram。我注意到Safari正在将电话样式文本更改为带有“ tel:”前缀的链接,因此我使用它来编写此代码,您可以对其进行测试: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>

1
您不应依靠这种技巧,因为用户或任何其他开发人员可以禁用电话检测。
БодровАндрей

@БодровАндрей我同意你的观点,但这是我唯一能找到的方法,我希望苹果将来能提供不同的User-Agent
Amir Khorsandi,

请注意,这在iOS 13上很糟糕,因为如果使用桌面模式,则navigator.platform === 'MacIntel'。这特别影响iPadOS 13 Mobile Safari,因为默认情况下它使用桌面模式。
robocat

@robocat你是对的。它在iOS 13 iPad中坏了,我现在无法解决。您能否在这里帮助我解决相关问题stackoverflow.com/questions/58344491/…–
newdeveloper,

2

Neoneye的解决方案不再起作用(请参阅注释),并且可以简化。另一方面,仅在UA中测试“ Safari”的功能要比ios手持设备好得多。

这是我正在使用的测试:

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

2

请注意,这种方法不适用于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 webview效果很好。


对于iPhone X,它将是375/812,也将是新的:对于iPhone Xs Max / Xr,它是414/896
Oleg Dater

1

Working 15.02.19

在iOS上检测Webview的另一种解决方案是检查是否支持navigator.mediaDevices

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

就我而言,我不需要捕获所有的Web视图,但是不需要捕获所有的Web视图(提醒:警报不会在Webview中触发,因此请确保为调试目的而更改dom中的某些内容)


0

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

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

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


谢谢,我正在使用该代码,但需要更多控制。似乎只能检测独立模式,而将其余模式视为Safari。
亚当·塔尔

0

建议使用Modernizr,并像这样检查indexeddb 。您可以通过用户代理配置(设备,操作系统,浏览器等)进行交叉检查,但是似乎更推荐使用纯功能检测。


听起来像是一个计划,但是您要测试什么功能?indexeddb是chrome,firefox等的一部分
SSED 2016年

0

上一次我需要这样做(仅出于WebView的目的)时,我使用了以下检查:

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

此问题在iOS13桌面模式(不再设置为iPad或iPhone的平台)和iPod touch(平台可以是“ iPod”或“ iPod touch”)上被打破。
robocat

0

我找到了一种检测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
    }

0

尝试使用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)

-2

我不认为可以在客户端Javascript中使用任何特定的东西,但是如果您可以控制原始UIWebView可以执行的操作,则可能需要考虑使用它生成的用户代理字符串,并在您的服务器中对此进行测试客户端Javascript代替?我知道一点点技巧,但是,嘿……这个问题可能会为调整用户代理提供一些指导:

在UIWebView中更改用户代理(iPhone SDK)


谢谢,本 不幸的是,我无法控制该应用程序的UIWebView用户代理。
亚当·塔尔

-7

@ Sod,好吧,我没有答案,但是我不确定您为什么要检查,因为浏览器引擎的浏览器(Browser)还是Application仅与Webkit相同,是的,Application可以配置Browser Engine功能,例如,无论应用程序要运行JS还是显示图像等…

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


您可以在评论中对此进行讨论。无论如何,有很多情况需要检查wevbview
Yozi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.