检测页面是不是在 JavaScript 中的 WKWebView 中加载

Posted

技术标签:

【中文标题】检测页面是不是在 JavaScript 中的 WKWebView 中加载【英文标题】:Detect if page is loaded inside WKWebView in JavaScript检测页面是否在 JavaScript 中的 WKWebView 中加载 【发布时间】:2015-03-01 15:44:24 【问题描述】:

如何使用 javascript 可靠地检测页面是否加载到 WKWebView 中?我希望能够检测到这些场景:

ios 和 WKWebView iOS 和 Safari 不是 iOS

关于 UIWebView here 也有类似的问题。但它已经很老了,我不确定 WKWebView 是否仍然适用。

【问题讨论】:

为什么?也许我们可以为您提供更好的方法来实现您的基本目标。 您不确定其他问题中描述的方法是否有效。那就试试吧! 如果在 WKWebView 中加载,页面的某些功能会有所不同。例如,它将使用原生类来优化文件上传。 我尝试了所有这些解决方案,但对我不起作用,请参阅我的answer 【参考方案1】:

接受的答案在使用WKWebView vs UIWebView app 测试时不起作用

正如文章所述,唯一的 html5 功能差异是 IndexedDB 支持。所以我会选择一个更可靠的模式:

    if (navigator.platform.substr(0,2) === 'iP')
      //iOS (iPhone, iPod or iPad)
      var lte9 = /constructor/i.test(window.HTMLElement);
      var nav = window.navigator, ua = nav.userAgent, idb = !!window.indexedDB;
      if (ua.indexOf('Safari') !== -1 && ua.indexOf('Version') !== -1 && !nav.standalone)      
        //Safari (WKWebView/Nitro since 6+)
       else if ((!idb && lte9) || !window.statusbar.visible) 
        //UIWebView
       else if ((window.webkit && window.webkit.messageHandlers) || !lte9 || idb)
        //WKWebView
      
    

您可能会问:为什么不使用 UserAgent?那是因为安卓浏览器使用它作为设置!所以,我们永远不应该相信任何 UA。仅限浏览器功能和属性检查。

我还注意到QuickTime 插件总是作为旧版 Safari 和 UIWebView 中其他浏览器的一部分加载。但是该插件不再存在于 WKWebView 中。所以你可以使用QuickTime 插件作为额外的检查。

9/23/16 编辑:我调整了 Safari 10 的代码,它不再允许唯一的 idb 检查是可靠的,正如 @xmnboy 所提到的。要放弃 Safari 10,它会检查旧的 webkit 引擎错误,该错误仅适用于 Safari 9.2;我使用了window.statusbar.visible 后备,在 iOS 9 和 10 之间进行了几次比较测试后,这似乎是一个可靠的指标信号。(请检查)

【讨论】:

不幸的是,这种方法不再有效。它在 iOS 9 设备上运行良好,但在 iOS 10 设备上,即使您在 UIWebView 中,对 window.indexedDB 的检查也会出现。 @xmnboy 好的,这并不奇怪。我有点怀疑这可能会发生。我要检查一下并寻找替代方案。 @xmnboy 我忘记了我实际上已经找到了另一个后备方案,在我的脚本中作为评论留下了方便,这似乎仍然是正确的,并且是 iOS10 的有效后备方案。 感谢您对检测机制的更新。 :-) window.statusbar.visible 对我们不起作用——在我们应用程序的 iOS10.3 上的 WKWebkitView 中确实如此。也许是因为我们的应用是全屏的?见wantsFullScreenLayout versus modalPresentationStyle of UIModalPresentationFullScreen。【参考方案2】:

鉴于 Apple 在 iOS 10 中引入的 UIWebView 的行为变化,这里有一个新的答案,它结合了 @Justin-Michael 的原始回复和 @hexalys 的后续最爱。

var isWKWebView = false ;
if( navigator.platform.substr(0,2) === 'iP' )     // iOS detected
    if( window.webkit && window.webkit.messageHandlers ) 
        isWKWebView = true ;
    

事实证明,Justin 的回答确实是更好的特征检测机制,因为它适用于 iOS 9 和 iOS 10。

不知道当我们进入 iOS 11 时会发生什么。:-)


资格:如果您使用 official Cordova WKWebView plugin 构建您的 webview 应用程序,此测试将有效,因为该插件确实初始化了 addScriptMessageHandler 方法,正如 cmets 中的 @hexalys 所指出的那样这个帖子。当存在 WKWebView 插件时,Cordova 正在使用该机制来定义一个新的 JS 到本机桥

在that plugin repo 中搜索addScriptMessageHandler 并查看该repo 中the ios-wkwebview-exec.js file 的最后部分以了解一些实现细节(或在该文件中搜索字符串window.webkit.messageHandlers)。

【讨论】:

同样,尽管 webkit 并不总是默认情况下在所有 iOS 视图上定义的对象。所以在 JS 方面不可靠。正如this answer 所述。 “window.webkit 命名空间仅出现在带有脚本消息处理程序的 webview 中。确保您已调用 WKUserContentController 的 addScriptMessageHandler 方法。”例如测试应用肯定没有设置它。 @hexalys -- 感谢您提供的额外知识。我已经更新了我的答案,包括关于我的测试环境的资格。我只关心在 Cordova(又名 Adob​​e PhoneGap 或 Intel XDK)构建环境中检测到 WKWebVew。【参考方案3】:

似乎是因为最新的iOS Chrome 使用WKWebView 作为渲染引擎,Chrome 被检测为WKWebView。 ua.indexOf('CriOS') !== -1 将有助于区分 Chrome 和 App 中的 WKWebView。

【讨论】:

【参考方案4】:

在iOS中,你可以添加这段代码来建立javascript和objective-c之间的通信:

WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKUserContentController *controller = [[WKUserContentController alloc] init];
[controller addScriptMessageHandler:self name:@"javascript_observer"];
configuration.userContentController = controller;

...

webview = [[WKWebView alloc] initWithFrame:... configuration: configuration];

在 javascript 中,您可以像这样测试连接:

if ( window.webkit != undefined )
//javascript is running in webview

【讨论】:

【参考方案5】:

您可以检查 WKWebKit 用于接收来自 JavaScript 的消息的 window.webkit.messageHandlers 是否存在。如果它存在,那么您就在 WKWebView 中。

结合简单的用户代理检查应该可以解决问题:

var iOS = (navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? true : false);
var isWKWebView = false;
if (window.webkit && window.webkit.messageHandlers) 
    isWKWebView = true;

【讨论】:

这听起来是个不错的解决方案。与 iOS 检查一起,它应该提供可靠的结果。 iOS 测试是错误的,因为它使用了用户代理(还检测到 android、WinPhone 8.1 更新等)。 /^iPhone|^iPad|^iPod/.test(navigator.platform) 之类的东西更好。请注意,“iPod touch”用于 iOS 8,因此请勿在 iPod 后添加 $。 这是唯一有效的答案。不是 iOS 检查,而是 messageHandlers 检查。

以上是关于检测页面是不是在 JavaScript 中的 WKWebView 中加载的主要内容,如果未能解决你的问题,请参考以下文章

如何在客户端使用 JavaScript 来检测页面是不是已加密?

使用 javascript/jquery 检测 Asp.Net 表单是不是有效

如何检测 Javascript 中的页面宽度和高度? [复制]

ASP 注册页面,同步检测用户名是不是已存在

检测是不是使用外部 JavaScript 文件创建了 html 元素

wk_10.md