2021年版 主要なアプリ内ブラウザのUserAgentを調べてみた & 判定を実装してみた
アプリ内ブラウザによって挙動が違うと、時にはグッとこらえてUserAgentによる条件分岐を入れなくてはいけないということもあるでしょう。
本当はこんな条件分岐入れたくない。でも、長い人生では止むに止まれぬ大人の事情というものがあります。
...さて、どう判定しよう? ざっと調べたところ少し古い情報しか見当たらなかったので、自分で調べてみました。
2021年6月27日時点、手元の
- iPhone 12 Pro(iOS 14.5)
- Pixel 4(Android 11)
を使って各アプリの(おそらく)最新版を使って調査しました。
それをもとに作成した、JavaScript (ES6)による実装例もつけてあります。間違いやもっといい方法などあればぜひコメントください。
テストコード付きの実装例はこちらから。
UserAgentの実例集め
対象にしたアプリは以下の通り:
- LINE
- Slack
- Discord
また、比較のためSafari(iOSのみ)とChromeも調べています。
iOS
Twitter、Slack、DiscordはSafariと全く同じUserAgentなので、判別不可能そうでした。Chrome、Facebook、Instagram、LINEは大丈夫です。
# Safari
Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1
# Chrome
Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/91.0.4472.80 Mobile/15E148 Safari/604.1
# Twitter
Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1
# Facebook
Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone13,3;FBMD/iPhone;FBSN/iOS;FBSV/14.5;FBSS/3;FBID/phone;FBLC/ja_JP;FBOP/5]
# Instagram
Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Instagram 193.0.0.29.121 (iPhone13,3; iOS 14_5; ja_JP; ja-JP; scale=3.00; 1170x2532; 299401192) NW/3
# LINE
Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Safari Line/11.10.0
# Slack
Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1
# Discord
Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1
Android
iOSと同様に、Twitter、Slack、DiscordはChromeと全く同じUserAgentなので、判別できなさそう。Facebook、Instagram、LINEは大丈夫です。
# Chrome
Mozilla/5.0 (Linux; Android 11; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36
# Twitter
Mozilla/5.0 (Linux; Android 11; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36
# Facebook
Mozilla/5.0 (Linux; Android 11; Pixel 4 Build/RQ2A.210405.005; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/90.0.4430.210 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/324.0.0.48.120;]
# Instagram
Mozilla/5.0 (Linux; Android 11; Pixel 4 Build/RQ2A.210405.005; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/90.0.4430.210 Mobile Safari/537.36 Instagram 193.0.0.45.120 Android (30/11; 440dpi; 1080x2236; Google/google; Pixel 4; flame; flame; ja_JP; 300078998)
# LINE
Mozilla/5.0 (Linux; Android 11; Pixel 4 Build/RQ2A.210405.005; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/90.0.4430.210 Mobile Safari/537.36 Line/11.10.2/IAB
# Slack
Mozilla/5.0 (Linux; Android 11; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36
# Discord
Mozilla/5.0 (Linux; Android 11; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36
判定する関数の実装
上記をもとに、どのアプリ内ブラウザかを判定する関数 detectInAppBrowser
を実装してみます。
window.navigator.userAgent
などで取得したUserAgentの文字列を渡すと、以下のように構成される文字列を返します。
(isまたはmaybe)_(アプリ)_(OS)
アプリは判定できたけどOSがわからない場合is_(アプリ)_unknown
のようになり、アプリを判定できなかった場合はnull
を返します。
テストコード付きのソースコードはこちらから。
/*
Detect in-app browser by UserAgent.
e.g. `console.log('your browser ' + detectInAppBrowser(navigator.userAgent))`
@param {string} ua UserAgent string
@returns {string | null} [is|maybe]_[safari|chrome|facebook|instagram|line]_[ios|android|unknown]
*/
export function detectInAppBrowser(ua) {
ua = ua.toLowerCase().trim();
// iOS Chrome
if (ua.includes('crios')) {
return 'is_chrome_ios';
}
const isIOS =
ua.includes('iphone') || ua.includes('ipod') || ua.includes('ipad');
const isAndroid = ua.includes('android');
// Facebook
if (ua.includes('fbios') || ua.includes('fb_iab')) {
return isIOS
? 'is_facebook_ios'
: isAndroid
? 'is_facebook_android'
: 'is_facebook_unknown';
}
// Instagram
if (ua.includes('instagram')) {
return isIOS
? 'is_instagram_ios'
: isAndroid
? 'is_instagram_android'
: 'is_instagram_unknown';
}
// LINE
if (ua.includes(' line/')) {
return isIOS
? 'is_line_ios'
: isAndroid
? 'is_line_android'
: 'is_line_unknown';
}
// iOS Safari|Twitter|Slack|Discord|etc
if (isIOS && /safari\/[0-9.]+$/.test(ua)) {
return 'maybe_safari_ios';
}
// Android Chrome|Twitter|Slack|Discord|etc
if (isAndroid && ua.includes('chrome') && /safari\/[0-9.]+$/.test(ua)) {
return 'maybe_chrome_android';
}
return null;
}
例えば、
const result = detectInAppBrowser(window.navigator.userAgent);
if (result.startsWith('is_facebook_')) {
console.log('Facebook');
if (result.endsWith('_ios')) {
console.log('のiOS版');
} else if (result.endsWith('_android')) {
console.log('のAndroid版');
}
console.log('ですね');
}
とすれば、FacebookのiOS版ですね
などを出力できます。
Discussion