Erkennen Sie, ob das Gerät iOS ist

408

Ich frage mich, ob es möglich ist, zu erkennen, ob ein Browser unter iOS ausgeführt wird, ähnlich wie Sie die Funktionserkennung mit Modernizr durchführen können (obwohl dies offensichtlich eher eine Geräteerkennung als eine Funktionserkennung ist).

Normalerweise würde ich stattdessen die Feature-Erkennung bevorzugen, aber ich muss herausfinden, ob ein Gerät iOS ist, da sie Videos gemäß dieser Frage verarbeiten. Die YouTube-API funktioniert nicht mit iPad / iPhone / Nicht-Flash-Geräten

SparrwHawk
quelle
Siehe [Was ist die iOS 5-Benutzeragentenzeichenfolge?] [1] (Duplikat?). [1]: stackoverflow.com/questions/7825873/…
dejuknow
1
Ist dies eine clientseitige oder serverseitige Erkennung?
Douglas Greenshields
Hey @DouglasGreenshields, es ist clientseitig
SparrwHawk
1
Auch kein Duplikat, ich frage, wie es geht. Ich habe noch nie zuvor User-Agent-Sniffing verwendet.
SparrwHawk

Antworten:

821

IOS erkennen

Ich bin kein Fan von User Agent-Schnüffeln, aber hier ist, wie Sie es tun würden:

var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

Ein anderer Weg ist, sich auf Folgendes zu verlassen navigator.platform:

var iOS = navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);

iOSwird entweder trueoder seinfalse

Warum nicht MSStream?

Microsoft hat das Wort iPhone in IE11s eingefügt, userAgentum Google Mail irgendwie zu täuschen. Deshalb müssen wir es ausschließen. Mehr Infos dazu hier und hier .

Unten ist IE11 aktualisiert userAgent(Internet Explorer für Windows Phone 8.1 Update):

Mozilla / 5.0 (Mobil; Windows Phone 8.1; Android 4.0; ARM; Trident / 7.0; Touch; RV: 11.0; IEMobile / 11.0; NOKIA; Lumia 930) wie iPhone OS 7_0_3 Mac OS X AppleWebKit / 537 (KHTML, wie Gecko) Mobile Safari / 537


Fügen Sie einfach weitere Geräte hinzu, ohne reguläre Ausdrücke zu verwenden:

function iOS() {

  var iDevices = [
    'iPad Simulator',
    'iPhone Simulator',
    'iPod Simulator',
    'iPad',
    'iPhone',
    'iPod'
  ];

  if (navigator.platform) {
    while (iDevices.length) {
      if (navigator.platform === iDevices.pop()){ return true; }
    }
  }

  return false;
}

iOS()wird entweder trueoder seinfalse

Hinweis: Beide navigator.userAgentund navigator.platformkönnen vom Benutzer oder einer Browser-Erweiterung gefälscht werden.


IOS-Version erkennen

Die häufigste Methode zum Erkennen der iOS-Version besteht darin, sie aus der User Agent-Zeichenfolge zu analysieren . Aber es gibt auch Feature Erkennung Inferenz * ;

Wir wissen für eine Tatsache, history APIdie in iOS4 eingeführt wurde - matchMedia APIin iOS5 - webAudio APIin iOS6 - WebSpeech APIin iOS7 und so weiter.

Hinweis: Der folgende Code ist nicht zuverlässig und funktioniert nicht, wenn eine dieser HTML5-Funktionen in einer neueren iOS-Version veraltet ist. Du wurdest gewarnt!

function iOSversion() {

  if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) {
    if (window.indexedDB) { return 'iOS 8 and up'; }
    if (window.SpeechSynthesisUtterance) { return 'iOS 7'; }
    if (window.webkitAudioContext) { return 'iOS 6'; }
    if (window.matchMedia) { return 'iOS 5'; }
    if (window.history && 'pushState' in window.history) { return 'iOS 4'; }
    return 'iOS 3 or earlier';
  }

  return 'Not an iOS device';
}
Pierre
quelle
2
Danke Pierre - dieser Code scheint jedoch einfacher zu sein. Ich frage mich nur, ob ich nur 'iOS' angeben kann, anstatt alle separaten iDevices eingeben zu müssen .... if ((navigator.userAgent.match (/ iPhone / i)) | | (navigator.userAgent.match (/ iPod / i)) || (navigator.userAgent.match (/ iPad / i)) {// Mach etwas}
SparrwHawk
9
Was Sie im zweiten Snippet tun, ist Feature-Inferenz, nicht Feature-Erkennung. Bei der Funktionserkennung werden Funktionen getestet, die Sie tatsächlich verwenden werden, während Sie Funktionen testen, von denen Sie zufällig wissen, dass sie in einer bestimmten Version des Betriebssystems eingeführt wurden, und daraus die Betriebssystemversion ableiten. Dies ist fragil, da zukünftige Versionen von iOS diese Funktionen entfernen könnten.
Tim Down
23
Dies ist ein besserer Weg, um Ihren Scheck zu schreiben:var iOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
LandonSchropp
5
Nur eine Anmerkung - das Array navigator.platform funktioniert auf dem iPad Simulator nicht, da die gesamte Zeichenfolge "iPad Simulator" in der Plattformzeichenfolge enthalten ist.
Kevin Newman
9
Ab iOS 13 hat sich der Benutzeragent des iPad beispielsweise in "Mac OS" geändert. Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15
Daher muss
38

Nach iOS 13 sollten Sie iOS-Geräte wie dieses erkennen, da das iPad auf alte Weise nicht als iOS-Geräte erkannt wird (aufgrund neuer "Desktop" -Optionen, die standardmäßig aktiviert sind):

let isIOS = /iPad|iPhone|iPod/.test(navigator.platform)
|| (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)

Die erste Bedingung für iOS <13 oder iPhone oder iPad mit deaktiviertem Desktop-Modus, die zweite Bedingung für iPadOS 13 in der Standardkonfiguration, da es sich wie Macintosh Intel positioniert, aber tatsächlich der einzige Macintosh mit Multi-Touch ist.

Eher ein Hack als eine echte Lösung, aber für mich zuverlässig arbeiten

PS Wie bereits erwähnt, sollten Sie wahrscheinlich die IE-Überprüfung hinzufügen

let isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream
Kikiwora
quelle
Warum nicht das navigator.userAgentfür diesen Check verwenden /iPad|iPhone|iPod/.test(navigator.platform)? Es scheint, dass navigator.platformimmer "MacIntel" für iPhone iOS <= 12
Charis Theo
@CharisTheo Weil iPad in iOS nicht im userAgent ist> = 13
Kzrbill
Aber Sie suchen bereits beim zweiten Check nach iPad iOS> = 13 oder fehlt mir etwas?
Charis Theo
navigator.maxTouchPointswird in iOS nicht unterstützt, sodass die Überprüfung nichts für Sie bedeutet.
PaulC
@PaulC, Sie haben Recht, dass maxTouchPoints für iOS 12 und niedriger undefiniert ist, aber kikiwora ist auf dem richtigen Weg, da maxTouchPoints in iOS 13 unterstützt wird. Siehe meine Antwort.
Bob Arlof
14

Dies setzt die Variable _iOSDeviceauf wahr oder falsch

_iOSDevice = !!navigator.platform.match(/iPhone|iPod|iPad/);
Vitim.us
quelle
3
was macht !! tun?
Patrick
4
@astronought doppelte Negation wird verwendet, um auf einen Booleschen
Wert zu setzen
2
@astronought Bang Bang, du bist boolean: D
Qback
1
Mit können /iPhone|iPod|iPad/.test(navigator.platform)Sie das!!
Lionello
10

Wenn Sie Modernizr verwenden , können Sie einen benutzerdefinierten Test hinzufügen.

Es spielt keine Rolle, für welchen Erkennungsmodus Sie sich entscheiden (userAgent, navigator.vendor oder navigator.platform), Sie können ihn jederzeit für eine spätere einfachere Verwendung einpacken.

//Add Modernizr test
Modernizr.addTest('isios', function() {
    return navigator.userAgent.match(/(iPad|iPhone|iPod)/g);
});

//usage
if (Modernizr.isios) {
    //this adds ios class to body
    Modernizr.prefixed('ios');
} else {
    //this adds notios class to body
    Modernizr.prefixed('notios');
}
ThiagoPXP
quelle
2
Seien Sie vorsichtig, Modernizr schreibt den Namen des hinzugefügten Tests automatisch in Kleinbuchstaben. (In Ihrem Beispiel wird Modernizr.isiOS niemals true zurückgeben.) Schlechtes Verhalten der
Bibliothek aus
3
Nur winziger Hinweis: Sie vereinfachen return x ? true : falsezu return Boolean(x)oder geradereturn !!x
Tibalt
6

Eine vereinfachte, einfach zu erweiternde Version.

var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
Kory Nunn
quelle
1
Wenn Sie möchten, dass dies auch unter iOS Simulator funktioniert, können Sie Folgendes verwenden : navigator.platform.replace(' Simulator', '').
Koraktor
Aber es funktioniert nicht, weil['str'].indexOf('string') == -1
Tibalt
navigator.platform ist genau "iPad", "iPhone" oder "iPod", sofern der Simulator nicht ausgeführt wird.
Kory Nunn
4

Es lohnt sich wahrscheinlich zu antworten, dass iPads mit iOS 13 navigator.platformeingestellt sind MacIntel, was bedeutet, dass Sie einen anderen Weg finden müssen, um iPadOS-Geräte zu erkennen.

Justin Searls
quelle
3

Ich habe das vor ein paar Jahren geschrieben, aber ich glaube, es funktioniert immer noch:

if(navigator.vendor != null && navigator.vendor.match(/Apple Computer, Inc./) && navigator.userAgent.match(/iPhone/i) || (navigator.userAgent.match(/iPod/i))) 

    {

        alert("Ipod or Iphone");

    }

else if (navigator.vendor != null && navigator.vendor.match(/Apple Computer, Inc./) && navigator.userAgent.match(/iPad/i))  

    {

        alert("Ipad");

    }

else if (navigator.vendor != null && navigator.vendor.match(/Apple Computer, Inc./) && navigator.userAgent.indexOf('Safari') != -1)

    {

        alert("Safari");

    }

else if (navigator.vendor == null || navigator.vendor != null)

    {

        alert("Not Apple Based Browser");

    }
Michael Benin
quelle
2

Die Benutzeragenten auf iOS-Geräten sagen iPhone oder iPad in ihnen. Ich filtere nur basierend auf diesen Schlüsselwörtern.

Bryan Naegele
quelle
4
Es gibt auch iPod Touches zu berücksichtigen.
Douglas Greenshields
@DouglasGreenshields Richtig. Ich habe das vergessen, aber ich glaube, es überträgt seine Identität auch im User-Agent.
Bryan Naegele
Der Benutzeragent der iPad-Safari wird "iPad" von iPadOS 13 nicht mehr enthalten.
Jonny
2

Wenn immer möglich, sollten Sie beim Hinzufügen von Modernizr-Tests einen Test für eine Funktion anstelle eines Geräts oder Betriebssystems hinzufügen. Es ist nichts Falsches daran, zehn Tests für alle iPhone-Tests hinzuzufügen, wenn dies erforderlich ist. Einige Dinge können einfach nicht erkannt werden.

    Modernizr.addTest('inpagevideo', function ()
    {
        return navigator.userAgent.match(/(iPhone|iPod)/g) ? false : true;
    });

Beispielsweise kann auf dem iPhone (nicht auf dem iPad) kein Video inline auf einer Webseite abgespielt werden, es wird im Vollbildmodus geöffnet. Also habe ich ein Test-No-Inpage-Video erstellt.

Sie können dies dann in CSS verwenden (Modernizr fügt .no-inpagevideodem <html>Tag eine Klasse hinzu , wenn der Test fehlschlägt).

.no-inpagevideo video.product-video 
{
     display: none;
}

Dadurch wird das Video auf dem iPhone ausgeblendet (in diesem Fall wird ein alternatives Bild mit einem Klick angezeigt, um das Video abzuspielen. Ich möchte nur nicht, dass der Standard-Videoplayer und die Wiedergabetaste angezeigt werden).

Simon_Weaver
quelle
iOS10 erlaubt jetzt, playsinlineso dass Sie 'playsInline' in document.createElement('video');jetzt als Test verwenden können github.com/Modernizr/Modernizr/issues/2077
Simon_Weaver
2

Wow, viel längerer kniffliger Code hier. Halte es einfach, bitte!

Dieser ist meiner Meinung nach schnell, sicher und funktioniert gut:

 iOS = /^iP/.test(navigator.platform);

 // or, more future-proof (in theory, probably not in practice):

 iOS = /^iP(hone|[ao]d)/.test(navigator.platform);

 // or, if you prefer readability:

 iOS = /^(iPhone|iPad|iPod)/.test(navigator.platform);
  • Es ist schnell, weil der reguläre Ausdruck die ^ s überprüft Position der Plattform String tarting ersten und stoppt , wenn es keine „iP“ ist (schneller als das lange UA String bis zum Ende der Suche sowieso)
  • Es ist sicherer als UA-Check (vorausgesetzt, navigator.platform ist weniger wahrscheinlich gefälscht)
  • Erkennt den iPhone / iPad Simulator


UPDATE: Dies gilt nicht für das iPad im Desktop-Modus (und daher für das Standard-iPadOS 13).
Das ist in Ordnung für meine Fälle, wenn es nicht für Sie ist, sehen Sie die Antworten von Justin und Kikiwora.

jj
quelle
iOS = /^(iPhone|iPad|iPod)/.test(navigator.platform);anstatt dies würde ich iOS = /^(iPhone|iPad|iPod)/.test(navigator.userAgent || navigator.vendor || navigator.platform); als Fallback-Maßnahme tun, weil in meinem Fall navigator.platform nicht funktioniert hat, aber es wie später zu tun hat gut funktioniert
Coderboi
navigator.platformhat nicht funktioniert? Bist du dann wirklich auf iOS? Überprüfen Sie mit jeka.info/test/navigator.html . userAgentgibt falsch positive Ergebnisse aus, da einige Anbieter es fälschen, um Apple-Geräte aus welchen Gründen auch immer nachzuahmen. vendorgerade Rückkehr entweder Google Inc., Apple Computer, Inc.oder nichts (in Firefox).
JJ
1

Aktualisieren Sie die erste Antwort leicht mit einem funktionaleren Ansatz.

    const isIOS = [
      'iPad Simulator',
      'iPhone Simulator',
      'iPod Simulator',
      'iPad',
      'iPhone',
      'iPod',
    ].indexOf(navigator.platform) !== -1;
Sten Muchow
quelle
Funktioniert nicht im mobilen Simulator von Brave / Chrome dev tools. Ich bekommeMacIntel
sdfsdf
1

Keine der vorherigen Antworten funktioniert für alle gängigen Browser unter allen iOS-Versionen, einschließlich iOS 13. Hier ist eine Lösung, die für Safari, Chrome und Firefox für alle iOS-Versionen funktioniert:

var isIOS = (function () {
    var iosQuirkPresent = function () {
        var audio = new Audio();

        audio.volume = 0.5;
        return audio.volume === 1;   // volume cannot be changed from "1" on iOS 12 and below
    };

    var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
    var isAppleDevice = navigator.userAgent.includes('Macintosh');
    var isTouchScreen = navigator.maxTouchPoints >= 1;   // true for iOS 13 (and hopefully beyond)

    return isIOS || (isAppleDevice && (isTouchScreen || iosQuirkPresent()));
})();

Beachten Sie, dass dieses Code-Snippet mit Priorität auf Lesbarkeit geschrieben wurde, nicht auf Prägnanz oder Leistung.

Erläuterung:

  • Wenn der Benutzeragent "iPod | iPhone | iPad" enthält, handelt es sich eindeutig um iOS. Ansonsten weiter ...

  • Jeder andere Benutzeragent, der keinen "Macintosh" enthält, ist kein Apple-Gerät und kann daher nicht iOS sein. Ansonsten handelt es sich um ein Apple-Gerät. Fahren Sie fort ...

  • Wenn maxTouchPointsder Wert 1mindestens größer ist, verfügt das Apple-Gerät über einen Touchscreen und muss daher iOS sein, da es keine Macs mit Touchscreens gibt (ein großes Lob an Kikiwora für die Erwähnung maxTouchPoints). Beachten Sie, dass maxTouchPointsist undefinedfür iOS 12 und unten, so dass wir eine andere Lösung für dieses Szenario benötigen ...

  • iOS 12 und niedriger hat eine Eigenart, die unter Mac OS nicht vorhanden ist. Die Besonderheit ist, dass die volumeEigenschaft eines AudioElements nicht erfolgreich auf einen anderen Wert als gesetzt werden kann 1. Dies liegt daran, dass Apple Audiofür iOS-Geräte keine Volumenänderungen für das Element zulässt , für Mac OS jedoch. Diese Eigenart kann als endgültige Fallback-Methode zur Unterscheidung eines iOS-Geräts von einem Mac OS-Gerät verwendet werden.

Bob Arlof
quelle
0

Sie können auch verwenden includes

  const isApple = ['iPhone', 'iPad', 'iPod'].includes(navigator.platform)
Alan
quelle
-1

In meinem Fall war der Benutzeragent nicht gut genug, da der Benutzeragent auf dem iPad derselbe war wie unter Mac OS, daher musste ich einen fiesen Trick machen:

var mql = window.matchMedia("(orientation: landscape)");

/**
 * If we are in landscape but the height is bigger than width
 */
if(mql.matches && window.screen.height > window.screen.width) {
    // IOS
} else {
    // Mac OS
}
Ian Farré
quelle
Lesen Sie einfach die Frage, die darin steht, iOS zu erkennen, nicht Handy zu erkennen
Cybersupernova
-2

Um die iOS-Version zu erkennen, muss der Benutzeragent mit einem Javascript-Code wie folgt zerstört werden:

 var res = navigator.userAgent.match(/; CPU.*OS (\d_\d)/);
    if(res) {
        var strVer = res[res.length-1];
        strVer = strVer.replace("_", ".");
        version = strVer * 1;
    }
viebel
quelle
-2

var isiOSSafari = (navigator.userAgent.match(/like Mac OS X/i)) ? true: false;

Mithun Sreedharan
quelle