Wykryj webview na iPadzie / iPhonie za pomocą javascript

91

Czy istnieje sposób, aby odróżnić się za pomocą javascript, jeśli witryna działa w iPadzie safari lub w aplikacji WebView?

darń
źródło
Czy to tylko dla urządzeń z iOS?
Nicolas S,

Odpowiedzi:

80

To używa kombinacji window.navigator.userAgenti window.navigator.standalone. Rozróżnia wszystkie cztery stany związane z aplikacją internetową na iOS: safari (przeglądarka), samodzielna (pełny ekran), uiwebview, a nie 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
};
Myślenie Sztywne
źródło
chrome ma Safariw userAgent. zachowuje się inaczej w odniesieniu do wymagania webcal://protokołu dla plików .ics
neaumusic
@svlada czy możesz podać więcej informacji? Jakie było Twoje urządzenie i jego wersja na iOS?
sonlexqt
Nie działa na iOS 13 i 14.
Alex Sorokoletov
78

Agenty użytkownika

Działa w UIWebView

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

Działa w Safari na iPadzie

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

Działa w Safari na 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

Działa w Chrome na 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

Działa w FireFox na Mac OS X

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

Kod wykrywania

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
źródło
Naprawdę. Nie wiem, dlaczego po prostu spojrzałem na oba useragents w pierwszej kolejności. Dzięki za odpowiedź :)
sod
4
Nie działa na iPhonie 5s / iOS 7, ponieważ oba UIWebViewi Safari mają Safariw swoim kliencie użytkownika
Razor
@Razor Masz rację. Testowanie przeciw, Versiona nie Safaridziałało dla mnie w najnowszym iOS.
unceus
1
@unceus Czy możesz dokładnie opisać, co masz na myśli Version? Czy zastąpić Safarize Versionw var is_uiwebviewwierszu?
Henrik Petterson
@HenrikPetterson W odniesieniu do ciągów agenta użytkownika, porównując pierwsze dwa ciągi agentów użytkownika powyżej (UIWebView i Safari na iPadzie), ciąg UIWebView zawiera „wersję”, podczas gdy w przypadku iPada nie. Twój cel modyfikacji wyrażenia regularnego jest niejasny i wygląda na to, że szukasz pomocy w jego napisaniu.
unceus
10

Myślę, że możesz po prostu użyć User-Agent.


AKTUALIZACJA

Strona przeglądana za pomocą 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

Spróbuję za chwilę z 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

Różnica polega na tym, że mówi Safari Safari/6531.22.7


Rozwiązanie

var isSafari = navigator.userAgent.match(/Safari/i) != null;
Nicolas S.
źródło
Tak, ale czy masz pojęcie, czy istnieje określony ciąg lub coś do wykrycia UIWebView w User-Agent? Jak dotąd nic nie mogłem znaleźć ...
Adam Tal
Czy to tylko dla urządzeń z iOS?
Nicolas S,
Nicolas, liczby będą w tej chwili inne, ponieważ Safari i UIWebView (oraz „samodzielne” - czyli ekran główny - aplikacje internetowe) korzystają z różnych silników. To zmienia się w iOS 5.
Ben
Nie chodzi mi o liczby, chodzi mi o to, że Safari/.....samego siebie brakuje w UIWebView
Nicolas S
@Nicolas: zgadza się, przepraszam, że nie zwracałem uwagi. Zastanawiam się, czy ktoś mógłby potwierdzić, czy w iOS5 nadal tak jest?
Ben
7

Tak:

// 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
źródło
11
Będzie to pasowało również do przeglądarki Safari, a nie tylko do WebView.
Petr Peller
@ThinkingStuff - Czy możesz mi pomóc w rozróżnieniu między systemem Mac OS (przeglądarka komputerowa) a przeglądarką Safari na iPadzie - stackoverflow.com/questions/58344491/…
newdeveloper
6

Wypróbowałem wszystkie te rozwiązania, ale nie zadziałały w moim przypadku,
zamierzałem wykryć Telegram w Webview. Zauważyłem, że Safari zmienia tekst w stylu telefonu na link z prefiksem „tel:”, więc użyłem tego do napisania tego kodu, możesz go przetestować: 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
źródło
1
Nie powinieneś polegać na takiej sztuczce, ponieważ użytkownik lub inni programiści mogą wyłączyć wykrywanie telefonu.
Бодров Андрей
@ БодровАндрей Zgadzam się z tobą, ale to był jedyny sposób, w jaki mogłem znaleźć, mam nadzieję, że Apple zapewni w przyszłości innego User-Agent
Amir Khorsandi
Uważaj, to jest zepsute na iOS 13, ponieważ jeśli używany jest tryb pulpitu, to navigator.platform === 'MacIntel'. Dotyczy to szczególnie iPadOS 13 Mobile Safari, ponieważ domyślnie używa trybu pulpitu.
robocat
@robocat masz rację. jest zepsuty w iPadzie z iOS 13 i teraz utknąłem bez rozwiązania. Czy mógłbyś mi pomóc z podobnym pytaniem tutaj stackoverflow.com/questions/58344491/…
newdeveloper
Działa to na iOS 14
Alex Sorokoletov
2

Rozwiązanie Neoneye już nie działa (patrz komentarze) i można je uprościć. Z drugiej strony, testowanie tylko „Safari” w UA oznacza znacznie więcej niż urządzenia przenośne z iOS.

Oto test, którego używam:

var is_ios = /(iPhone|iPod|iPad).*AppleWebKit.*Safari/i.test(navigator.userAgent);
eosfera
źródło
2

Zwróć uwagę, że to podejście nie działa w przypadku iOS 10 i starszych wersji.

Na wiosnę 2018 roku żadna z proponowanych metod nie zadziałała, więc wymyśliłem nowe podejście (które nie jest oparte na 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

Możesz również rozszerzyć kod na urządzenia iPad, myślę, że powinno to załatwić sprawę.

Działał dobrze w przypadku widoków internetowych Telegram, Facebook, VK.

Boris Chumichev
źródło
Dla iPhone'a X byłoby to 375/812, również nowość: 414/896 dla iPhone Xs Max / Xr
Oleg Dater
1

Working 15.02.19

Innym rozwiązaniem służącym do wykrywania wyświetleń stron internetowych w systemie iOS jest sprawdzanie obsługi / istnienia navigator.mediaDevices.

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

W moim przypadku nie musiałem przechwytywać wszystkich odsłon internetowych, ale te, które nie obsługują wejścia kamery / mikrofonu (Przypomnienie: Alerty nie uruchamiają się w Webview, więc pamiętaj, aby zmienić coś w dom do celów debugowania)

vinni
źródło
0

Wiem, że ten kod sprawdzi, czy jest dostępny z ikony dodanej do ekranu głównego:

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

ale nie jestem pewien, jak by zareagował w UIWebView. Jedyne inne rozwiązanie, o którym mógłbym pomyśleć, to pobranie agenta użytkownika lub użycie - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationTypei zastąpienie ciągu zapytania strony, do której uzyskujesz dostęp, czymś, czego strona używa do zidentyfikowania, że ​​uzyskuje się do niej dostęp z widoku sieci Web.

Preston
źródło
Dzięki, używałem tego kodu, ale potrzebuję większej kontroli. Wydaje się, że wykrywa tylko tryb autonomiczny, a resztę uważa za Safari.
Adam Tal
0

Sugerowałbym użycie Modernizr i sprawdzenie indexeddb w ten sposób . Możesz to sprawdzić w konfiguracji agenta użytkownika (urządzenie, system operacyjny, przeglądarka itp.), Ale bardziej zalecane jest wykrywanie samych funkcji.

jiku
źródło
Brzmi jak plan, ale jakie funkcje chciałbyś przetestować? indexeddb jest częścią ie, chrome, firefox etc
SSED
0

Ostatnim razem, gdy tego potrzebowałem (TYLKO do celów WebView), użyłem tego sprawdzenia:

function isIOS() {
     return !/safari/.test( window.navigator.userAgent.toLowerCase()) || navigator.platform === 'iOS' || navigator.platform === 'iPhone';
}
CatalinBerta
źródło
Jest to zepsute w trybie pulpitu iOS13 (platforma nie jest już ustawiona na iPada lub iPhone'a) i na iPodzie touch (platformą może być „iPod” lub „iPod touch”).
robocat
0

Znalazłem proste rozwiązanie do wykrywania iPhone'a lub iPada. U mnie to działa dobrze.

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
źródło
0

Wypróbuj z 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
źródło
-2

Nie sądzę, aby było coś konkretnego, czego można by użyć w JavaScript po stronie klienta, ale jeśli masz kontrolę nad tym, co może zrobić początkowy UIWebView, możesz rozważyć zabawę z ciągiem agenta użytkownika, który generuje, i przetestowanie tego w swoim Zamiast tego JavaScript po stronie klienta? Trochę hack, wiem, ale hej… To pytanie może dać kilka wskazówek na temat ulepszania agenta użytkownika:

Zmień klienta użytkownika w UIWebView (iPhone SDK)

Ben
źródło
Dzięki, Ben. Niestety nie mam kontroli nad agentem użytkownika UIWebView aplikacji.
Adam Tal
-7

@ Cholera, cóż, nie mam odpowiedzi, ale nie jestem przekonany, dlaczego chcesz sprawdzić, ponieważ silnik przeglądarki, czy jego safari (przeglądarka) lub aplikacja będzie taka sama, tylko Webkit, tak Aplikacja może skonfigurować funkcje silnika przeglądarki, takie jak , czy aplikacja chce uruchamiać JS lub Display Image itp…

Uważam, że musisz sprawdzić pod kątem określonej właściwości, czy Flash jest obsługiwany przez przeglądarkę lub czy przeglądarka wyświetla obraz, czy nie, a może chcesz sprawdzić rozmiar ekranu,

Amitg2k12
źródło
możesz omówić to w komentarzach. W każdym razie jest wiele przypadków, aby sprawdzić wevbview
Yozi