detectar webview ipad / iphone a través de javascript

91

¿Hay alguna forma de diferenciar a través de javascript si el sitio web se ejecuta dentro del ipad safari o dentro de una aplicación WebView?

césped
fuente
¿Es esto solo para dispositivos iOS?
Nicolas S

Respuestas:

79

Esto usa una combinación de window.navigator.userAgentywindow.navigator.standalone . Puede distinguir entre los cuatro estados relacionados con una aplicación web de iOS: safari (navegador), independiente (pantalla completa), uiwebview y no iOS.

Demostración: 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
};
Pensando rígido
fuente
Chrome tiene Safarien userAgent. se comporta de manera diferente con respecto al webcal://protocolo requerido para archivos .ics
neaumusic
@svlada ¿puede proporcionar más información? ¿Cuál era su dispositivo y su versión de iOS?
sonlexqt
78

Agentes de usuario

Ejecutando en UIWebView

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

Ejecutar en Safari en 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

Ejecutar en Safari en 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

Ejecutando en Chrome en 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

Ejecutando en FireFox en Mac OS X

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

Código de detección

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);
neoneye
fuente
De Verdad. No sé por qué solo miré a ambos agentes de usuario en primer lugar. Gracias por tu respuesta :)
sod
4
No funciona en iPhone 5s / iOS 7, porque ambos UIWebViewy Safari tienen Safarien su agente de usuario
Razor
@Razor Tienes razón. Probar en contra Versionen lugar de Safaritrabajar para mí en el último iOS.
Incenso
1
@unceus ¿Puedes describir exactamente a qué te refieres con Version? ¿Reemplaza Safaricon Versionen la var is_uiwebviewlínea?
Henrik Petterson
@HenrikPetterson Con respecto a las cadenas de agentes de usuario, comparando las dos primeras cadenas de agentes de usuario anteriores (UIWebView y Safari en iPad), la cadena UIWebView contiene 'versión' mientras que la de ipad no. Su objetivo al modificar la expresión regular no está claro y parece que podría estar buscando ayuda para escribir una.
incesante
10

Creo que puedes usar el User-Agent.


ACTUALIZAR

Página navegada con Safari de iPhone

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

Lo intentaré en un segundo 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 diferencia es que el de Safari dice Safari/6531.22.7


Solución

var isSafari = navigator.userAgent.match(/Safari/i) != null;
Nicolas S
fuente
Sí, pero ¿tiene alguna idea de si hay una cadena específica o algo para detectar UIWebView en el User-Agent? Hasta ahora no pude encontrar nada ...
Adam Tal
¿Es esto solo para dispositivos iOS?
Nicolas S
Nicolas, los números serán diferentes en este momento porque Safari y UIWebView (y las aplicaciones web "independientes", es decir, la pantalla de inicio) utilizan motores diferentes. Esto cambia en iOS 5.
Ben
No me refiero a los números, me refiero Safari/.....a que falta el mismo en UIWebView
Nicolas S
@Nicolas: Muy bien, siento no haber prestado atención. Me pregunto si alguien podría confirmar si este sigue siendo el caso en 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);
John Doherty
fuente
11
Esto coincidirá también con el navegador Safari, no solo con WebView.
Petr Peller
@ThinkingStuff - ¿Me podría ayudar a ayuda diiferentiate entre Mac OS (navegador de escritorio) y el navegador Safari del iPad - stackoverflow.com/questions/58344491/...
newdeveloper
5

Probé todas estas soluciones pero no funcionó en mi caso,
iba a detectar Telegram dentro de Webview. Me di cuenta de que Safari está cambiando el texto del estilo del teléfono a un enlace con el prefijo "tel:", así que usé esto para escribir este código, puedes probarlo: 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>
Amir Khorsandi
fuente
1
No debe confiar en ese truco porque el usuario o cualquier otro desarrollador puede desactivar la detección telefónica.
Бодров Андрей
@ БодровАндрей Estoy de acuerdo contigo, pero esa fue la única forma que pude encontrar, espero que Apple proporcione un agente de usuario diferente para eso en el futuro
Amir Khorsandi
Tenga en cuenta que esto es borken en iOS 13, porque si se usa el modo de escritorio, entonces navigator.platform === 'MacIntel'. Esto afecta especialmente a iPadOS 13 Mobile Safari porque usa el modo de escritorio de forma predeterminada.
robocat
@robocat tienes razón. está roto en el iPad iOS 13 y ahora estoy atascado sin una solución. ¿Me ayuda con la pregunta relacionada aquí stackoverflow.com/questions/58344491/...~~V~~singular~~3rd
newdeveloper
2

La solución de Neoneye ya no funciona (ver comentarios) y se puede simplificar. Por otro lado, probar solo "Safari" en la UA aborda mucho más que los dispositivos de mano ios.

Esta es la prueba que estoy usando:

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

Tenga en cuenta que este enfoque no funciona para iOS 10 y versiones anteriores.

Para la primavera de 2018, ninguno de los métodos propuestos funcionó para mí, así que se me ocurrió un nuevo enfoque (que no está basado en 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

También puede ampliar el código para dispositivos iPad, creo que debería funcionar.

Funcionó bien para Telegram, Facebook, VK webviews.

Boris Chumichev
fuente
Para iPhone X sería 375/812, también nuevo: 414/896 para iPhone Xs Max / Xr
Oleg Dater
1

Working 15.02.19

Otra solución para detectar vistas web en iOS es verificar el soporte / existencia de navigator.mediaDevices.

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

En mi caso, no necesitaba capturar todas las vistas web, pero las que no admiten la entrada de cámara / micrófono (Recordatorio: las alertas no se activan en la vista web, así que asegúrese de cambiar algo en el dom para fines de depuración)

vinni
fuente
0

Sé que este código comprobará si se accede a él desde un icono añadido a la pantalla de inicio:

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

pero no estoy seguro de cómo reaccionaría en un UIWebView. La única otra solución que se me ocurre es obtener el agente de usuario o usar - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationTypey reemplazar la cadena de consulta de la página a la que está accediendo por algo que la página usa para identificar que se está accediendo desde una vista web.

Preston
fuente
Gracias, estaba usando ese código, pero necesito más control. Parece que solo detecta el modo independiente y considera que el resto es Safari.
Adam Tal
0

Sugeriría usar Modernizr y verificar indexeddb como este . Puede verificarlo con la configuración del agente de usuario (dispositivo, sistema operativo, navegador, etc.), pero la detección de funciones pura parece más recomendable.

jiku
fuente
Suena como un plan, pero ¿qué funciones probarías? indexeddb es parte de ie, chrome, firefox, etc.
SSED
0

La última vez que necesité esto (SOLO para propósitos de WebView), utilicé esta verificación:

function isIOS() {
     return !/safari/.test( window.navigator.userAgent.toLowerCase()) || navigator.platform === 'iOS' || navigator.platform === 'iPhone';
}
CatalinBerta
fuente
Esto no funciona en el modo de escritorio iOS13 (la plataforma ya no está configurada para iPad o iPhone) y en el iPod touch (la plataforma puede ser "iPod" o "iPod touch").
robocat
0

Encontré una solución simple para detectar iPhone o iPad. Esto funciona bien para mí.

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
    }
Vijay Dhanvai
fuente
0

Prueba 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)
Mahmoud D. Alghraibeh
fuente
-2

No creo que haya nada específico que pueda usar en Javascript del lado del cliente, pero si tiene control sobre lo que puede hacer el UIWebView de origen, es posible que desee considerar jugar con la cadena de agente de usuario que genera y probarlo en su ¿Javascript del lado del cliente en su lugar? Es un truco, lo sé, pero bueno ... Esta pregunta puede dar algunos consejos sobre cómo modificar el agente de usuario:

Cambiar el agente de usuario en UIWebView (iPhone SDK)

Ben
fuente
Gracias, Ben. Desafortunadamente, no tengo control sobre el agente de usuario UIWebView de la aplicación.
Adam Tal
-7

@ Sod, bueno, no tengo la respuesta, pero no estoy convencido de por qué desea verificar, ya que el motor del navegador si su safari (navegador) o la aplicación será el mismo, solo su Webkit, sí, la aplicación puede configurar las capacidades del motor del navegador como , ya sea que la aplicación quiera ejecutar JS o Display Image, etc.

Creo que debe verificar cierta propiedad si Flash es compatible con el navegador o si el navegador muestra una imagen o no, o probablemente le gustaría verificar el tamaño de la pantalla,

Amitg2k12
fuente
podría discutir esto en los comentarios. De todos modos, hay muchos casos para verificar wevbview
Yozi