奇葩需求之:js判断浏览器环境,是webview?安卓App?苹果浏览器?还是微信浏览器打开的。

需求描述:js脚本判断网页是在什么环境中打开的。内置浏览器,还是app内嵌入式的webview打开的,亦或是在微信浏览器内打开的,还是用pc端打开的。

查了一圈资料,原理基本上就是通过navigator对象上的信息来做文章,更具体一点是,navigator.userAgent这个对象上的信息。

借鉴(chāo xí)zepto.js的浏览器嗅探代码,改写为下面这样的。

// 浏览器嗅探
export function detect(navigator) {
  let ua = navigator.userAgent;
  let platform = navigator.platform;
  let os = {},
    browser = {},
    webkit = ua.match(/Web[kK]it[\/]{0,1}([\d.]+)/),
    android = ua.match(/(Android);?[\s\/]+([\d.]+)?/),
    osx = !!ua.match(/\(Macintosh\; Intel /),
    ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
    ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/),
    iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
    webos = ua.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),
    win = /Win\d{2}|Windows/.test(platform),
    wp = ua.match(/Windows Phone ([\d.]+)/),
    touchpad = webos && ua.match(/TouchPad/),
    kindle = ua.match(/Kindle\/([\d.]+)/),
    silk = ua.match(/Silk\/([\d._]+)/),
    blackberry = ua.match(/(BlackBerry).*Version\/([\d.]+)/),
    bb10 = ua.match(/(BB10).*Version\/([\d.]+)/),
    rimtabletos = ua.match(/(RIM\sTablet\sOS)\s([\d.]+)/),
    playbook = ua.match(/PlayBook/),
    chrome = ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/),
    firefox = ua.match(/Firefox\/([\d.]+)/),
    firefoxos = ua.match(/\((?:Mobile|Tablet); rv:([\d.]+)\).*Firefox\/[\d.]+/),
    ie =
      ua.match(/MSIE\s([\d.]+)/) ||
      ua.match(/Trident\/[\d](?=[^\?]+).*rv:([0-9.].)/),
    webview =
      !chrome && ua.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/),
    safari =
      webview ||
      ua.match(/Version\/([\d.]+)([^S](Safari)|[^M]*(Mobile)[^S]*(Safari))/),
    weixin = ua.match(/MicroMessenger/i);

  // if (browser.webkit = !!webkit) browser.version = webkit[1]
  if (webkit) {
    browser.webkit = !!webkit;
    browser.version = webkit[1];
  }

  if (android) (os.android = true), (os.version = android[2]);
  if (iphone && !ipod)
    (os.ios = os.iphone = true), (os.version = iphone[2].replace(/_/g, "."));
  if (ipad)
    (os.ios = os.ipad = true), (os.version = ipad[2].replace(/_/g, "."));
  if (ipod)
    (os.ios = os.ipod = true),
      (os.version = ipod[3] ? ipod[3].replace(/_/g, ".") : null);
  if (wp) (os.wp = true), (os.version = wp[1]);
  if (webos) (os.webos = true), (os.version = webos[2]);
  if (touchpad) os.touchpad = true;
  if (blackberry) (os.blackberry = true), (os.version = blackberry[2]);
  if (bb10) (os.bb10 = true), (os.version = bb10[2]);
  if (rimtabletos) (os.rimtabletos = true), (os.version = rimtabletos[2]);
  if (playbook) browser.playbook = true;
  if (kindle) (os.kindle = true), (os.version = kindle[1]);
  if (silk) (browser.silk = true), (browser.version = silk[1]);
  if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true;
  if (chrome) (browser.chrome = true), (browser.version = chrome[1]);
  if (firefox) (browser.firefox = true), (browser.version = firefox[1]);
  if (firefoxos) (os.firefoxos = true), (os.version = firefoxos[1]);
  if (ie) (browser.ie = true), (browser.version = ie[1]);
  if (safari && (osx || os.ios || win)) {
    browser.safari = true;
    if (!os.ios) browser.version = safari[1];
  }
  if (webview) browser.webview = true;
  if (weixin) browser.wx = true; // 微信浏览器

  os.tablet = !!(
    ipad ||
    playbook ||
    (android && !ua.match(/Mobile/)) ||
    (firefox && ua.match(/Tablet/)) ||
    (ie && !ua.match(/Phone/) && ua.match(/Touch/))
  );
  os.phone = !!(
    !os.tablet &&
    !os.ipod &&
    (android ||
      iphone ||
      webos ||
      blackberry ||
      bb10 ||
      (chrome && ua.match(/Android/)) ||
      (chrome && ua.match(/CriOS\/([\d.]+)/)) ||
      (firefox && ua.match(/Mobile/)) ||
      (ie && ua.match(/Touch/)))
  );
  return { os, browser };
}

使用的时候,

// 把detect 函数引入需要使用的地方
import { detect } from "@/utils/index";
//.....省略
 let res = detect(navigator);
      console.log(res); // {os: {iphone: true, ios: true, version: "11.0", tablet: false, phone: true}, browser: {webkit: true, version: "604.1.38", safari: true}}
    },

具体使用方式,大家可以自定义了。

我在测试中,遇到的问题,是,在自己开发的App中,使用的是webview加载页面,无法判断是不是webview,打印出来navigator.userAgent和在小米手机自带的浏览器中的,是一模一样的,根本就无法判断是不是在app中通过webview打开的。

这个也不难理解,他们的浏览器,也是套了一个webview的壳而已。

那如何解决,是不是用app内打开的呢?

让安卓开发人员,在开发的时候,添加一些标志信息到userAgent中去吧。

	// 修改ua使得web端正确判断
	String ua = webview.getSettings().getUserAgentString();
	webview.getSettings().setUserAgentString(ua+"; MYAPP/"+appversion);

具体链接可以参考:http://www.jincon.com/archives/354/

然后,我们把这个标签信息,添加到我们上面写的判断中去。微信浏览器不就是加了MicroMessenger这个标志么。原理一样。

猜你喜欢

转载自blog.csdn.net/qq_42991509/article/details/106995357