rilevare ipad / iphone webview tramite javascript


91

C'è un modo per differire tramite javascript se il sito web viene eseguito all'interno di ipad safari o all'interno di un'applicazione WebView?


È solo per i dispositivi iOS?
Nicolas S

Risposte:


79

Questo utilizza una combinazione di window.navigator.userAgente window.navigator.standalone. Può distinguere tra tutti e quattro gli stati relativi a un'app Web iOS: safari (browser), standalone (a schermo intero), uiwebview e non iOS.

Demo: 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 ha Safariin userAgent. si comporta diversamente per quanto riguarda la richiesta del webcal://protocollo per i file .ics
neaumusic

@svlada puoi fornire maggiori informazioni? Qual era il tuo dispositivo e la sua versione iOS?
sonlexqt

78

Agenti utente

In esecuzione in UIWebView

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

In esecuzione in Safari su iPad

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

In esecuzione in Safari su Mac OS X

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

In esecuzione in Chrome su Mac OS X

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

In esecuzione in FireFox su Mac OS X

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

Codice di rilevamento

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

Veramente. Non so perché ho esaminato personalmente entrambi gli useragents in primo luogo. Grazie per la tua risposta :)
sod

4
Non funziona su iPhone 5s / iOS 7, perché entrambi UIWebViewe Safari hanno Safarinel loro agente utente
Razor

@Razor Hai ragione. Il test rispetto Versional contrario ha Safarifunzionato per me nell'ultimo iOS.
unceus

1
@unceus Puoi delineare esattamente come intendi con Version? Sostituisci Safaricon Versionin var is_uiwebviewlinea?
Henrik Petterson

@HenrikPetterson Per quanto riguarda le stringhe dell'agente utente, confrontando le prime due stringhe dell'agente utente sopra (UIWebView e Safari su iPad) la stringa UIWebView contiene 'versione' mentre quella dell'ipad no. Il tuo obiettivo con la modifica della regex non è chiaro e sembra che tu stia cercando aiuto per scriverne uno.
unceus

10

Penso che tu possa semplicemente usare il file User-Agent.


AGGIORNARE

Pagina sfogliata utilizzando 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

Proverò tra un secondo con 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

La differenza è che dice quello di Safari Safari/6531.22.7


Soluzione

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

Sì, ma hai idea se c'è una stringa specifica o qualcosa per rilevare UIWebView in User-Agent? Finora non sono riuscito a trovare nulla ...
Adam Tal,

È solo per i dispositivi iOS?
Nicolas S

Nicolas, i numeri al momento saranno diversi perché Safari e UIWebView (e "stand-alone", ovvero la schermata iniziale, le app web) utilizzano motori diversi. Questo cambia in iOS 5.
Ben

Non intendo i numeri, voglio dire che Safari/.....manca lo stesso nella UIWebView
Nicolas S,

@Nicolas: giusto, scusa se non stavo prestando attenzione. Mi chiedo se qualcuno possa confermare se questo è ancora il caso in iOS5?
Ben

7

Si:

// 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
Questo corrisponderà anche al browser Safari non solo a WebView.
Petr Peller

@ThinkingStuff - Potrebbe aiutarmi aiuto diiferentiate tra Mac OS (browser desktop) e il browser Safari per iPad - stackoverflow.com/questions/58344491/...
newdeveloper

5

Ho provato tutte queste soluzioni ma non ha funzionato nel mio caso,
stavo per rilevare Telegram all'interno di Webview. Ho notato che Safari sta cambiando il testo in stile telefono in un collegamento con il prefisso "tel:", quindi l'ho usato per scrivere questo codice, puoi provarlo: 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
Non dovresti fare affidamento su questo trucco perché l'utente o altri sviluppatori possono disabilitare il rilevamento del telefono.
Бодров Андрей

@ БодровАндрей Sono d'accordo con te, ma questo era l'unico modo che ho potuto trovare, spero che Apple fornisca un diverso User-Agent per questo in futuro
Amir Khorsandi

Attenzione, questo è borken su iOS 13, perché se viene utilizzata la modalità desktop, allora navigator.platform === 'MacIntel'. Ciò influisce in particolare su iPadOS 13 Mobile Safari perché utilizza la modalità desktop per impostazione predefinita.
robocat

@robocat hai ragione. è rotto in iOS 13 iPad e in questo momento sono bloccato senza una soluzione. La prego di aiutarmi con domanda relativa qui stackoverflow.com/questions/58344491/...~~V~~singular~~3rd
newdeveloper

2

La soluzione di Neoneye non funziona più (vedi commenti) e può essere semplificata. D'altra parte, testare solo "Safari" nell'UA indirizza molto di più rispetto ai dispositivi palmari ios.

Questo è il test che sto usando:

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

2

Tieni presente che questo approccio non funziona per iOS 10 e versioni precedenti.

Per la primavera del 2018 nessuno dei metodi proposti ha funzionato per me, quindi ho escogitato un nuovo approccio (che non è basato su 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

Sei libero di estendere il codice anche per i dispositivi iPad, penso che dovrebbe fare il trucco.

Ha funzionato bene per le visualizzazioni web di Telegram, Facebook, VK.


Per iPhone X sarebbe 375/812, anche nuovo: 414/896 per iPhone Xs Max / Xr
Oleg Dater

1

Working 15.02.19

Un'altra soluzione per rilevare le visualizzazioni Web su iOS è verificare il supporto / l'esistenza di navigator.mediaDevices.

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

Nel mio caso non avevo bisogno di catturare tutte le visualizzazioni web, ma quelle che non supportano l'ingresso da videocamera / microfono (Promemoria: gli avvisi non si attivano in Webview, quindi assicurati di cambiare qualcosa nel dom per scopi di debug)


0

So che questo codice controllerà se vi si accede da un'icona aggiunta alla schermata principale:

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

ma non sono sicuro di come reagirebbe in un UIWebView. L'unica altra soluzione a cui potrei pensare è ottenere l'agente utente o utilizzare - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationTypee sostituire la stringa di query della pagina a cui stai accedendo con qualcosa che la pagina utilizza per identificare l'accesso da una visualizzazione web.


Grazie, stavo usando quel codice, ma ho bisogno di più controllo. Sembra rilevare solo la modalità standalone e considera il resto come Safari.
Adam Tal,

0

Suggerirei di utilizzare Modernizr e di controllare indexeddb in questo modo . È possibile effettuare un controllo incrociato con la configurazione dell'agente utente (dispositivo, sistema operativo, browser, ecc.), Ma il rilevamento delle funzionalità puro sembra più consigliato.


Sembra un piano, ma per quali funzionalità testeresti? indexeddb fa parte di ie, chrome, firefox ecc.
SSED

0

L'ultima volta che ne avevo bisogno (SOLO per scopi WebView), ho usato questo controllo:

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

Questo non funziona in modalità desktop iOS13 (la piattaforma non è più impostata su iPad o iPhone) e su iPod touch (la piattaforma può essere "iPod" o "iPod touch").
robocat

0

Ho trovato una soluzione semplice per rilevare iPhone o iPad. Questo per me funziona bene.

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

Prova con 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

Non penso che ci sia qualcosa di specifico che puoi usare in Javascript lato client, ma se hai il controllo su ciò che può fare l'UIWebView di origine, potresti prendere in considerazione la possibilità di giocare con la stringa dell'agente utente che genera e testarlo nel tuo Javascript lato client invece? Un po 'un trucco lo so, ma hey ... Questa domanda potrebbe fornire alcuni suggerimenti su come modificare il programma utente:

Cambia agente utente in UIWebView (iPhone SDK)


Grazie, Ben. Sfortunatamente non ho il controllo sull'agente utente UIWebView dell'app.
Adam Tal

-7

@ Sod, beh non ho una risposta, ma non sono convinto del motivo per cui vuoi controllare, dal momento che il motore del browser se il suo safari (browser) o l'applicazione sarà lo stesso solo del suo Webkit, Sì L'applicazione può configurare le funzionalità del motore del browser come , se l'applicazione desidera eseguire JS o Display Image ecc ...

Credo che sia necessario verificare determinate proprietà se Flash è supportato dal browser o se il browser visualizza o meno l'immagine, o probabilmente si desidera controllare le dimensioni dello schermo,


potresti discuterne nei commenti. Comunque ci sono molti casi per controllare wevbview
Yozi
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.