JavaScriptでmacOSとiPadOSを識別する
2019年秋にリリース予定のiOS13ですがiPadではiOSとは別のiPadOSが使われるようになります。このiPadOS上のSafariではユーザエージェントが大きく変更されて、macOS上のSafariと見分けがつかなくなってしまいました。今回はWebアプリケーション内でiPadOSを識別するための方法を説明します。
注意: 今回はWebアプリケーション(html5/javascriptで構築したアプリ)に関する話でネイティブアプリには関係ありません。また、サーバー側での判定ではなくクライアント側(JavaScript)での判定の話になります。
2019.10.9追記
iPadの実機で確認したところ、実機ではユーザエージェント文字列に従来のiOSと同じように"iPad"の文字列が入っていました。ユーザエージェントが区別できなかったのはシミュレーターのバグだったのか?と思ったのですが、その後いろいろいじってみたところ、Safariの設定メニューに[デスクトップ用Webサイトを表示]という項目があり、これのOn/Offでユーザエージェント文字列が切り替わるようです。この設定がシミュレータだとデフォルトでOn、実機ではOffになっていたため、シミュレーターと実機でユーザエージェント文字列が異なっているように見えていただけのようです。
ユーザがPCと同じ表示をさせたいと明示的に設定した場合は、Macと同じユーザエージェントにして、表示ができるだけPCと同じになるようにするというわけですね。ただ、多くのWebサイトだとユーザエージェント文字列は参照せず、スクリーンの横幅に応じてレスポンシブ表示するケースが多いと思うので結局スマホ/タブレット用の表示になってしまいそうですが。
結局、iPadOSのユーザエージェントがmacOSと区別できなくなるのは、ユーザがデスクトップ用Webサイトを表示したいと明示的に設定した場合なので、そこで無理矢理iPadであることを検出して処理を分ける必要もないような気がします。本ページの判定処理も結局不要になりそうですが、一応、追加で調べたユーザエージェント情報を以下に追記しておきます。
==追記ここまで==
電子カタログ等のWebアプリケーションを開発しているとブラウザやプラットフォームの種類を判定して処理を分けたいケースがよくあります。
上に書いたとおり、iPadOS上のSafariはユーザエージェントがMacのSafariと同じになっており、ユーザエージェントからは判断できなくなっています(ユーザエージェント文字列の例は以下参照)。
参考: iPhone,iPad,Mac上の各種ブラウザのユーザエージェント
[Safari on iPhone + iOS13] Mozilla/5.0 (iPhone; CPU iPhone OS 13_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/604.1 [Safari on iPad + iOS12] Mozilla/5.0 (iPad; CPU OS 12_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1 [Safari on iPad + iPadOS13(デスクトップ用Webサイトを表示:On設定時)] Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15 [Safari on iPad + iPadOS13(デスクトップ用Webサイトを表示:Off設定時)] ※2019.10.9追記 Mozilla/5.0 (iPad; CPU OS 13_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.1 Mobile/15E148 Safari/604.1 [Safari on macOS Mojave] Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Safari/605.1.15 [Chrome on macOS Mojave] Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36 [Firefox on macOS Mojave] Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0
[Safari on iPad + iPadOS]と[Safari on macOS Mojave]のユーザエージェントを比較すると、バージョン番号の細かい違いはありますが、基本的に同じ内容になっているのがわかります。
iPadはIntelじゃなくてARMでは?という気もしますがAppleとしてはiPadOSはmacOSと同じように見せたい(扱わせたい)ということなのかもしれません。
以上からユーザーエージェントによる判定は無理そうなので、別の手段を考えます。
ブラウザにはwindow.navigator.platformというオブジェクトがあり、これでプラットフォームを識別することができるかもと思いましたが、navigator.platformの値は表1のとおりになっていました。
表1 ブラウザごとのnavigator.platformの値
Platform | OS | Browser | navigator.platform値 | 備考 |
---|---|---|---|---|
iPhone | iOS13 | Safari | iPhone | |
iPad | iOS12 | Safari | iPad | |
iPad | iPadOS13 | Safari | MacIntel | デスクトップ用Webサイトを表示設定がOnの時 |
iPad | iPadOS13 | Safari | iPad | デスクトップ用Webサイトを表示設定がOffの時 ※2019.10.9追記 |
Mac | macOS Mojave | Safari,Chrome,Firefox | MacIntel |
iOS12まではiPadのnavigator.platformは"iPad"でしたが、iPadOSのSafariのnavigator.platformは"MacIntel"となっており、こちらもmacOSのSafariと区別が付きません。
結局、iPadOSのSafariにあってmacOSのSafariに存在しない機能/プロパティを利用するしかなさそうだったので、探したところnavigator.standaloneが使えそうでした。
navigator.standaloneとはWebページがフルスクリーンモードで表示されているかを示すプロパティで、macOSのSafariには存在しません(undefinedになる)。
ということで以下のような判定処理にしました。
macOS上のSafariかiPadOS上のSafariか判定するJavaScriptコード例
if (navigator.platform == "MacIntel" && navigator.userAgent.indexOf("Safari") != -1 && navigator.userAgent.indexOf("Chrome") == -1) { if (navigator.standalone !== undefined) { // iPad OS Safari } else { // macOS Safari } }
一応これでWebアプリケーション内で処理を分けることができます。
もっとスマートな方法を見つけたら更新していきます。
[補足]
以上から〜iOS12およびiPadOSを含むiPad判定は以下のようになります。
iPad判定処理
if (navigator.platform == "iPad" || // -iOS12 (navigator.platform == "MacIntel" && // iPadOS navigator.userAgent.indexOf("Safari") != -1 && navigator.userAgent.indexOf("Chrome") == -1 && navigator.standalone !== undefined)) { // iPad }
2019.9.8 一部誤記を修正(IntelMac→MacIntel)。
2019.10.9 Safariの設定によるユーザエージェント文字列の変更について追記。
投稿日:2019/08/20 13:56
タグ: Webアプリ JavaScript