detectar ipad / iphone webview via javascript

91

Existe uma maneira de diferenciar via javascript se o site for executado dentro do ipad safari ou dentro de um aplicativo WebView?

sod
fonte
Isso é apenas para dispositivos iOS?
Nicolas S de

Respostas:

79

Isso usa uma combinação de window.navigator.userAgente window.navigator.standalone. Ele pode distinguir entre todos os quatro estados relacionados a um aplicativo da web iOS: safari (navegador), autônomo (tela inteira), uiwebview e não 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
};
ThinkingStiff
fonte
o cromo tem Safarino userAgent. ele se comporta de maneira diferente em relação à webcal://
solicitação de
@svlada você pode fornecer mais informações? Qual era o seu dispositivo e sua versão iOS?
sonlexqt
78

Agentes de usuário

Executando em UIWebView

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

Executando no Safari no 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

Executando no Safari no 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

Executando no Chrome no 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

Executando no FireFox no Mac OS X

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

Código de Detecção

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
fonte
Realmente. Eu não sei por que eu mesmo olhei para os dois useragents em primeiro lugar. Obrigado pela sua resposta :)
sod
4
Não funciona no iPhone 5s / iOS 7, porque ambos UIWebViewe Safari têm Safariem seu agente de usuário
Razor
@Razor Você está certo. Testar Versionem oposição a Safarifuncionou para mim no iOS mais recente.
unceus
1
@unceus Você pode descrever exatamente o que você quer dizer com Version? Você substitui Safaricom Versionna var is_uiwebviewlinha?
Henrik Petterson
@HenrikPetterson Com relação às strings do agente do usuário, comparando as duas primeiras strings do agente do usuário acima (UIWebView e Safari no iPad), a string UIWebView contém 'versão', enquanto a do ipad não contém. Seu objetivo com a modificação da regex não está claro e parece que você está procurando ajuda para escrever uma.
unceus
10

Eu acho que você pode simplesmente usar o User-Agent.


ATUALIZAR

Página navegada usando 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

Vou tentar em um segundo com 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

A diferença é que o Safari diz Safari/6531.22.7


Solução

var isSafari = navigator.userAgent.match(/Safari/i) != null;
Nicolas S
fonte
Sim, mas você tem alguma ideia se existe uma string específica ou algo para detectar UIWebView no User-Agent? Até agora não consegui encontrar nada ...
Adam Tal
Isso é apenas para dispositivos iOS?
Nicolas S de
Nicolas, os números serão diferentes no momento porque Safari e UIWebView (e "autônomos" - ou seja, tela inicial - aplicativos da web) usam mecanismos diferentes. Isso muda no iOS 5.
Ben
Não quero dizer os números, quero dizer que o Safari/.....próprio está faltando no UIWebView
Nicolas S
@Nicolas: certo, desculpe, não estava prestando atenção. Eu me pergunto se alguém poderia confirmar se este ainda é o caso no iOS5?
Ben
7

Sim:

// 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
fonte
11
Isso também corresponderá ao navegador Safari, não apenas ao WebView.
Petr Peller
@ThinkingStuff - Você poderia me ajudar a diferenciar entre o Mac OS (navegador desktop) e o navegador Safari do iPad - stackoverflow.com/questions/58344491/…
newdeveloper
5

Eu tentei todas essas soluções, mas não funcionou no meu caso,
eu ia detectar o Telegram dentro do Webview. Percebi que o Safari está mudando o texto do estilo do telefone para um link com o prefixo "tel:", então usei isso para escrever este código, você pode testá-lo: 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
fonte
1
Você não deve confiar em tal truque porque o usuário ou qualquer outro desenvolvedor pode desativar a detecção de telefone.
Бодров Андрей
@ БодровАндрей Eu concordo com você, mas foi a única maneira que pude encontrar, espero que a apple forneça um User-Agent diferente para isso no futuro
Amir Khorsandi
Cuidado, isso é borken no iOS 13, porque se o modo Desktop for usado, então navigator.platform === 'MacIntel'. Isso afeta especialmente o iPadOS 13 Mobile Safari porque ele usa o modo Desktop por padrão.
robocat
@robocat você está certo. está quebrado no iOS 13 iPad e agora estou preso sem uma solução. Você poderia me ajudar com a questão relacionada aqui stackoverflow.com/questions/58344491/…
newdeveloper
2

A solução do Neoneye não funciona mais (ver comentários) e pode ser simplificada. Por outro lado, testar apenas o "Safari" no UA aborda muito mais do que os dispositivos portáteis ios.

Este é o teste que estou usando:

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

Observe que essa abordagem não funciona para iOS 10 e versões anteriores.

Para a primavera de 2018, nenhum dos métodos propostos funcionou para mim, então eu vim com uma nova abordagem (que não é baseada em 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

Você é bem-vindo para estender o código para dispositivos iPad também, acho que deve servir.

Funcionou bem para webviews de Telegram, Facebook e VK.

Boris Chumichev
fonte
Para o iPhone X, seria 375/812, também novo: 414/896 para iPhone Xs Max / Xr
Oleg Dater
1

Working 15.02.19

Outra solução para detectar webviews no iOS é verificar o suporte / existência de navigator.mediaDevices.

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

No meu caso, não precisei capturar todas as visualizações da web, mas aquelas que não suportam entrada de câmera / microfone (lembrete: os alertas não são acionados no Webview, portanto, certifique-se de alterar algo no dom para fins de depuração)

vinni
fonte
0

Sei que este código verificará se ele está sendo acessado por um ícone adicionado à tela inicial:

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

mas não tenho certeza de como isso reagiria em um UIWebView. A única outra solução que eu poderia pensar é obter o agente do usuário ou usar - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationTypee substituir a string de consulta da página que você está acessando por algo que a página usa para identificar que está sendo acessada de uma visualização da web.

Preston
fonte
Obrigado, estava usando esse código, mas preciso de mais controle. Parece detectar apenas o modo autônomo e considera o resto como o Safari.
Adam Tal de
0

Sugiro usar o Modernizr e verificar indexeddb como este . Você pode verificar isso com a configuração do agente do usuário (dispositivo, sistema operacional, navegador, etc), mas a detecção de recursos pura parece mais recomendada.

Jiku
fonte
Parece um plano, mas quais recursos você testaria? indexeddb é parte do ie, chrome, firefox etc
SSED
0

Da última vez que precisei disso (SÓ para fins de WebView), usei esta verificação:

function isIOS() {
     return !/safari/.test( window.navigator.userAgent.toLowerCase()) || navigator.platform === 'iOS' || navigator.platform === 'iPhone';
}
CatalinBerta
fonte
Isso não funciona no iOS13 Desktop Mode (a plataforma não está mais configurada para iPad ou iPhone) e no iPod touch (a plataforma pode ser "iPod" ou "iPod touch").
robocat
0

Eu encontrei uma solução simples para detectar iPhone ou iPad. Isso funciona bem para mim.

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
fonte
0

Experimente com 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
fonte
-2

Não acho que haja algo específico que você possa usar em Javascript do lado do cliente, mas se você tiver controle sobre o que o UIWebView de origem pode fazer, você pode querer brincar com a string do agente do usuário que ele gera e testar isso em seu Javascript do lado do cliente? Um pouco hack, eu sei, mas ei ... Esta pergunta pode dar algumas dicas sobre como ajustar o agente do usuário:

Alterar o agente do usuário em UIWebView (iPhone SDK)

Ben
fonte
Obrigado, Ben. Infelizmente, não tenho controle sobre o agente de usuário UIWebView do aplicativo.
Adam Tal de
-7

@ Sod, bem, eu não tenho resposta, mas não estou convencido por que você deseja verificar, uma vez que, o mecanismo do navegador se seu safari (navegador) ou aplicativo será o mesmo seu Webkit apenas, Sim O aplicativo pode configurar os recursos do mecanismo do navegador, como , se o aplicativo deseja executar JS ou Display Image etc ...

Acredito que você deve verificar certas propriedades se o Flash é compatível com o navegador ou se o navegador exibe imagem ou não, ou provavelmente você gostaria de verificar o tamanho da tela,

Amitg2k12
fonte
você poderia discutir isso nos comentários. De qualquer forma, existem muitos casos para verificar wevbview
Yozi