Определить веб-просмотр 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 для целей отладки)
В прошлый раз, когда я нуждался в этом (ТОЛЬКО для целей 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 на стороне клиента вместо? Я знаю что-то вроде хака, но эй... Этот вопрос может дать некоторые советы по настройке пользовательского агента:
@ Sod, Ну, у меня нет ответа, но я не уверен, почему вы хотите проверить, так как, движок браузера, будет ли его Safari (Браузер) или Приложение таким же, как и его Webkit, Да, Приложение может настроить такие возможности движка Браузера, как хочет ли приложение запустить JS или Display Image и т. д.
Я считаю, что вы должны проверить для определенного свойства, поддерживает ли Flash браузер или браузер отображает изображение или нет, или, возможно, вы хотели бы проверить размер экрана,