Определить веб-просмотр ipad/iphone с помощью javascript

Есть ли способ отличить с помощью javascript, если веб-сайт работает внутри ipad Safari или внутри приложения WebView?

16 ответов

Решение

Это использует комбинацию window.navigator.userAgent а также window.navigator.standalone, Он может различать все четыре состояния, относящиеся к веб-приложению iOS: safari (браузер), автономный (полноэкранный), uiwebview и не iOS.

Демо: 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
};

Агенты пользователей

Запуск в UIWebView

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

Запуск в Safari на 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

Запуск в Safari на 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

Запуск в Chrome на 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

Запуск в FireFox на Mac OS X

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

Код обнаружения

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

Я думаю, что вы можете просто использовать User-Agent,


ОБНОВИТЬ

Страница просматривается с помощью 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

Попробую через секунду с 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

Разница в том, что сафари говорит Safari/6531.22.7


Решение

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

Я пробовал все эти решения, но в моем случае ничего не получалось,
Я собирался обнаружить Telegram внутри Webview. Я заметил, что Safari меняет текст в стиле телефона на ссылку с префиксом "tel:", поэтому я использовал это для написания этого кода, вы можете проверить его: 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>

Сейчас 2022 год, а версия Safari 15.4. Ни одно из вышеперечисленных решений не сработало для меня. В iOS есть два класса веб-просмотра: WKWebView и SFSafariViewController. SFSafariViewController имеет тот же пользовательский агент, что и Safari. Решение, которое я придумал, зависит от того, как height: 100vhобрабатывается в Mobile Safari. 100vh — это высота экрана устройства, а не видимая высота документа.

Для получения дополнительной информации см.:

https://developers.google.com/web/updates/2016/12/url-bar-изменение размера

https://bugs.webkit.org/show_bug.cgi?id=141832

https://github.com/bokand/URLBarSizing

Итак, в iOS такая функция определяет режим WebView.

      function isWebView()
{
    const htmlEl = document.getElementsByTagName('html')[0];
    const bodyEl = document.getElementsByTagName('body')[0];

    const oldHtmlHeight = htmlEl.style.height;
    const oldBodyHeight = bodyEl.style.height;

    htmlEl.style.height = "100vh";
    bodyEl.style.height = "100%";

    const webViewMode = document.documentElement.clientHeight === document.documentElement.scrollHeight;

    // restore height
    htmlEl.style.height = oldHtmlHeight;
    bodyEl.style.height = oldBodyHeight;

    return webViewMode;
}

Да уж:

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

Обратите внимание, что этот подход не работает для iOS 10 и более старых версий.

В течение весны 2018 года ни один из предложенных методов не работал для меня, поэтому я предложил новый подход (который не основан на userAgent):

const hasValidDocumentElementRatio =
  [ 320 / 454 // 5, SE
  , 375 / 553 // 6, 7, 8
  , 414 / 622 // 6, 7, 8 Plus
  , 375 / 635 // X
  ].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

Вы также можете расширить код для устройств iPad, я думаю, это должно сработать.

Хорошо работал для Telegram, Facebook, ВКонтакте.

Решение Neoneye больше не работает (см. Комментарии) и может быть упрощено. С другой стороны, тестирование только "Safari" в UA адресует гораздо больше, чем портативные устройства ios.

Это тест, который я использую:

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

Попробуйте с 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)

Working 15.02.19

Другое решение для обнаружения веб-просмотров на iOS - проверка поддержки / существования navigator.mediaDevices,

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

В моем случае мне не нужно было перехватывать все веб-просмотры, но те, которые не поддерживают вход с камеры / микрофона (Напоминание: оповещения не запускаются в веб-просмотре, поэтому обязательно измените что-либо в dom для целей отладки)

Рекомендую использовать Modernizr и проверять indexeddb следующим образом. Вы можете перепроверить это с конфигурацией пользовательского агента (устройство, ОС, браузер и т. Д.), Но простое обнаружение функций кажется более рекомендуемым.

В прошлый раз, когда я нуждался в этом (ТОЛЬКО для целей WebView), я использовал эту проверку:

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

Я нашел простое решение для обнаружения iPhone или iPad. Это работает для меня нормально.

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
    }

Я знаю, что этот код проверит, доступен ли он по значку, добавленному на домашний экран:

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

но я не уверен, как это отреагирует в UIWebView. Единственное другое решение, о котором я мог подумать, это получить пользовательский агент или использовать - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType и замену строки запроса страницы, к которой вы обращаетесь, чем-то, что страница использует для определения того, что к ней обращаются из веб-представления.

Я не думаю, что есть что-то конкретное, что вы можете использовать в клиентском Javascript, но если у вас есть контроль над тем, что может делать исходный UIWebView, вы можете подумать о том, чтобы поиграть со строкой пользовательского агента, которую он генерирует, и проверить это в своем Javascript на стороне клиента вместо? Я знаю что-то вроде хака, но эй... Этот вопрос может дать некоторые советы по настройке пользовательского агента:

Изменить пользовательский агент в UIWebView (iPhone SDK)

@ Sod, Ну, у меня нет ответа, но я не уверен, почему вы хотите проверить, так как, движок браузера, будет ли его Safari (Браузер) или Приложение таким же, как и его Webkit, Да, Приложение может настроить такие возможности движка Браузера, как хочет ли приложение запустить JS или Display Image и т. д.

Я считаю, что вы должны проверить для определенного свойства, поддерживает ли Flash браузер или браузер отображает изображение или нет, или, возможно, вы хотели бы проверить размер экрана,

Другие вопросы по тегам