在 JavaScript 中检测页面是否加载到 WKWebView 中

Detect if page is loaded inside WKWebView in JavaScript

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

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

您可以检查 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;
}

已接受的答案在使用 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呢?那是因为 Android 浏览器使用它作为设置!所以,我们永远不应该相信任何 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 之间进行了几次比较测试后,它似乎是一个可靠的指标信号。(请检查)

考虑到 Apple 在 iOS10 中引入的 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 方法,正如@hexalys 在对此 post 的评论中指出的那样。当 WKWebView 插件存在时,Cordova 正在使用该机制为本机桥 定义一个新的 JS。

在该存储库的 that plugin repo and see the very end of the ios-wkwebview-exec.js file 中搜索 addScriptMessageHandler 以了解一些实施细节(或在该文件中搜索字符串 window.webkit.messageHandlers)。

好像是因为最新的iOSChrome使用了WKWebView作为渲染引擎,所以Chrome被检测为WKWebView

ua.indexOf('CriOS') !== -1 

将有助于区分 Chrome 和 App 中的 WKWebView。

在 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
}