web-dev-qa-db-fra.com

Détecter si la page est chargée dans WKWebView en JavaScript

Comment puis-je détecter de manière fiable en utilisant javascript qu'une page est chargée dans un WKWebView? Je voudrais pouvoir détecter ces scénarios:

  • iOS et WKWebView
  • iOS et Safari
  • pas iOS

Il y a une question similaire à propos d'UIWebView ici . Mais c'est assez ancien et je ne suis pas sûr que cela s'applique toujours à WKWebView.

20
andr111

La réponse acceptée ne fonctionne pas comme testé à l'aide de l'application WKWebView vs UIWebView

Comme le mentionne l'article, la seule différence entre les fonctionnalités HTML5 est la prise en charge d'IndexedDB. Je choisirais donc un modèle plus fiable avec:

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

Vous pouvez demander: Pourquoi ne pas utiliser UserAgent? C'est parce que Android l'utilisent comme paramètres! Donc, nous ne devons jamais faire confiance aux UA. Seules les fonctionnalités du navigateur et les vérifications de propriétés en tant que telles.

J'ai également remarqué que le plugin QuickTime était toujours chargé dans le cadre de Safari plus ancien et d'autres navigateurs dans UIWebView. Mais le plugin n'est plus présent dans WKWebView. Vous pouvez donc utiliser la présence du plugin QuickTime comme vérification supplémentaire.

23/09/16 Edit: J'ai ajusté le code pour Safari 10 qui ne permettait plus à la vérification unique de l'idb d'être fiable, comme mentionné par @xmnboy. Pour supprimer Safari 10, il vérifie l'ancien bogue du moteur de kit Web, qui ne s'appliquait que jusqu'à Safari 9.2; et j'utilise un window.statusbar.visible repli qui semble être un signal indicateur fiable après quelques tests de comparaison entre iOS 9 et 10. (veuillez vérifier cependant)

29
hexalys

Compte tenu du changement de comportement de l'UIWebView qui a été introduit par Apple dans iOS 10, voici une nouvelle réponse qui combine la réponse originale de @ Justin-Michael et le favori de suivi de @hexalys.

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

Il s'avère que la réponse de Justin était vraiment le meilleur mécanisme de détection des fonctionnalités, car il fonctionne à la fois pour iOS 9 et iOS 10.

Je ne dis pas ce qui se passe quand on arrive à iOS 11. :-)


Qualification: ce test fonctionnera si vous utilisez le plug-in officiel Cordova WKWebView pour créer votre application de visualisation Web, car ce plug-in ne initialisez la méthode addScriptMessageHandler, comme indiqué par @hexalys dans les commentaires de cet article. Ce mécanisme est utilisé par Cordova pour définir un nouveau JS vers le pont natif lorsque le plugin WKWebView est présent.

Recherchez addScriptMessageHandler dans ce plugin repo et voyez la fin de le ios-wkwebview-exec.js fichier dans ce dépôt pour certains détails d'implémentation (ou recherchez la chaîne window.webkit.messageHandlers dans ce fichier).

4
xmnboy

Il semble qu'en raison du dernier iOS Chrome utilisant WKWebView comme moteur de rendu, Chrome est détecté comme WKWebView. Ua.indexOf ('CriOS')! == -1 aidera à distinguer Chrome de WKWebView dans l'application.

0
Chung-Hsien Chang

Dans iOS, vous pouvez ajouter ce code pour établir une communication entre javascript et 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];

En javascript, vous pouvez tester la connexion comme ceci:

if ( window.webkit != undefined ){
//javascript is running in webview
}
0
Jarir