`

判断是否是手机访问及手机操作系统

    博客分类:
  • Java
阅读更多

我们现在做的项目,移动端和PC端网站访问的是同一套接口,那么如何在接口中区分是手机访问还是PC短访问呢?

核心思想:根据请求头(request header)来判断,如何请求没有header或伪造user agent则无法判断.

先看一些user agent的实例:

Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0

Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) (Engine, like URL) Mobile/12B440 MicroMessenger/6.0.1 NetType/3G+

 

Mozilla/5.0 (Linux; U; Android 4.1.1; en-cn; HTC T528d) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 MicroMessenger/6.0.2.58_r984381.520 NetType/WIFI

 

Mozilla/5.0 (Linux; U; Android 4.2.2; zh-CN; 2013023 Build/HM2013023) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/9.9.5.489 U3/0.8.0 Mobile Safari/533.1

 

Opera/9.80 (Android 2.3.7; Linux; Opera Mobi/46154) Presto/2.11.355 Version/12.10

 

Mozilla/5.0 (Linux; U; Android 4.2.1; zh-cn; HUAWEI G700-U00 Build/HuaweiG700-U00) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 V1_AND_SQ_5.3.1_196_YYB_D QQ/5.3.1.2335 NetType/WIFI

 

Mozilla/5.0 (Linux; U; Android 4.0.4; zh-cn; HS-EG906 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 MicroMessenger/5.3.1.67_r745169.462

 

Mozilla/5.0 (Linux; U; Android 4.4.2; zh-cn; GT-I9500 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.0 QQ-Manager Mobile Safari/537.36



 

以下是我封装的一套方法

ClientOsInfo 是用于保存访问设备信息的,结构如下(省略getter,setter):

public class ClientOsInfo {
	/***
	 * 比如 Android_3.0
	 */
	private String osTypeVersion;
	/***
	 * Pad或Phone
	 */
	private String deviceType;
	/***
	 * os type
	 */
	private String osType;
	/***
	 * 只是版本号,例如"4.1.1"
	 */
	private String version;
	private String userAgent;
/***
	 * 是否是移动设备
	 * @return
	 */
	public boolean isMobile(){
		return (!ValueWidget.isNullOrEmpty(this.deviceType));
	}
}

 核心方法:

	/***
	 * 当移动端(手机或Pad)访问网页时获取移动端操作系统信息
	 * @param request
	 * @return
	 */
	public static ClientOsInfo getMobileOsInfo(HttpServletRequest request){
		String userAgent=request.getHeader("user-agent");
		if(ValueWidget.isNullOrEmpty(userAgent)){
			userAgent=request.getHeader("User-Agent");
		}
		ClientOsInfo info= HeaderUtil.getMobilOS(userAgent);
		info.setUserAgent(userAgent);
		return info;
	}

 

核心工具类:用于解析user agent

package com.common.util;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.common.bean.ClientOsInfo;
import com.string.widget.util.ValueWidget;

/***
 * 
 * @author huangwei
 * @since 2013-08-15
 */
public class HeaderUtil {
	public static final String OSTYPE_ANDROID="Android";
	public static final String OSTYPE_IOS="Ios";
	public static final String OSTYPE_WP="WINDOWS PHONE";
	public static final String OSTYPE_BLACKBERRY="BLACKBERRY";
	/***
	 * pad
	 */
	public static final String DEVICE_TYPE_PAD="Pad";
	/***
	 * 手机
	 */
	public static final String DEVICE_TYPE_PHONE="Phone";


	/***
	 * 校验渠道终端版本号是否合法,eg:0.0.0.3
	 * 
	 * @param clientVersion
	 * @return true-->合法 ;false-->非法
	 */
	public static boolean verifyClientVersion(String clientVersion) {
		boolean result = Pattern.matches("[\\d\\.]+", clientVersion);
		if (result) {
			result = Pattern.matches("^\\d\\.\\d\\.\\d\\.\\d$", clientVersion);
			return result;
		} else {
			return false;
		}
	}
	
	/**
	 * 根据useragent和手机厂商查手机型号
	 * 
	 * @param UA
	 * @param vendor
	 * @return
	 */
	public static String getMobModel(String UA, String operatingSystem) {
		if (UA == null) {
			return null;
		}
		// 存放正则表达式
		String rex = "";
		// 苹果产品
		if (operatingSystem.indexOf("IOS") != -1) {
			if (UA.indexOf("IPAD") != -1) {// 判断是否为ipad
				return "IPAD";
			}
			if (UA.indexOf("IPOD") != -1) {// 判断是否为ipod
				return "IPOD";
			}
			if (UA.indexOf("IPONE") != -1) {// 判断是否为ipone
				return "IPONE";
			}
			return "IOS DEVICE";

		}
		// 安卓系统产品
		if (operatingSystem.indexOf("ANDROID") != -1) {
			String re = "BUILD";
			rex = ".*" + ";" + "(.*)" + re;
			Pattern p = Pattern.compile(rex, Pattern.CASE_INSENSITIVE);
			Matcher m = p.matcher(UA);
			boolean rs = m.find();
			if (rs) {
				System.out.println("Mobil Model is" + m.group(1));
				return m.group(1);
			}
		}
		return null;
	}

	/**
	 * 判断手机的操作系统 IOS/android/windows phone/BlackBerry
	 * 
	 * @param UA
	 * @return
	 */
	public static ClientOsInfo getMobilOS(String UA) {
		UA=UA.toUpperCase();
		if (UA == null) {
			return null;
		}
		ClientOsInfo osInfo=new  ClientOsInfo();
		// 存放正则表达式
		String rex = "";
		// IOS 判断字符串
		String iosString = " LIKE MAC OS X";
		if (UA.indexOf(iosString) != -1) {
			if(isMatch(UA, "\\([\\s]*iPhone[\\s]*;", Pattern.CASE_INSENSITIVE)){
				osInfo.setDeviceType(DEVICE_TYPE_PHONE);
			}else if(isMatch(UA, "\\([\\s]*iPad[\\s]*;", Pattern.CASE_INSENSITIVE)){
				osInfo.setDeviceType(DEVICE_TYPE_PAD);
			}
			rex = ".*" + "[\\s]+(\\d[_\\d]*)" + iosString;
			Pattern p = Pattern.compile(rex, Pattern.CASE_INSENSITIVE);
			Matcher m = p.matcher(UA);
			boolean rs = m.find();
			if (rs) {
				String osVersion= m.group(1).replace("_", ".");
				osInfo.setVersion(osVersion);
//				System.out.println("Mobil OS is" + " IOS" +osVersion);
				osInfo.setOsTypeVersion(OSTYPE_IOS+"_" + osVersion);
			}else{
				System.out.println("IOS");
				osInfo.setOsTypeVersion(OSTYPE_IOS);
			}
			osInfo.setOsType(OSTYPE_IOS);
			return osInfo;
		}
		// Android 判断
		String androidString = "ANDROID";
		if (UA.indexOf(androidString) != -1) {
			if(isMatch(UA, "\\bMobi", Pattern.CASE_INSENSITIVE)){
				osInfo.setDeviceType(DEVICE_TYPE_PHONE);
			}else {
				osInfo.setDeviceType(DEVICE_TYPE_PAD);
			}
			rex = ".*" + androidString + "[\\s]*(\\d*[\\._\\d]*)";
			Pattern p = Pattern.compile(rex, Pattern.CASE_INSENSITIVE);
			Matcher m = p.matcher(UA);
			boolean rs = m.find();
			if (rs) {
				String version=m.group(1).replace("_", ".");
				osInfo.setVersion(version);
				System.out.println("Mobil OS is " + OSTYPE_ANDROID + version);
				osInfo.setOsTypeVersion(OSTYPE_ANDROID+"_" + version);
			}else{
				System.out.println("Android");
				osInfo.setOsTypeVersion(OSTYPE_ANDROID);
			}
			osInfo.setOsType(OSTYPE_ANDROID);
			return osInfo;
		}
		// windows phone 判断
		String wpString = "WINDOWS PHONE";
		if (UA.indexOf(wpString) != -1) {
			rex = ".*" + wpString + "[\\s]*[OS\\s]*([\\d][\\.\\d]*)";
			Pattern p = Pattern.compile(rex, Pattern.CASE_INSENSITIVE);
			Matcher m = p.matcher(UA);
			boolean rs = m.find();
			if (rs) {
				System.out.println("Mobil OS is " + OSTYPE_WP + m.group(1));
				String version=m.group(1);
				osInfo.setVersion(version);
				osInfo.setOsTypeVersion(OSTYPE_WP+"_" + version);
			}else{
				System.out.println("WINDOWS PHONE");
				osInfo.setOsTypeVersion(OSTYPE_WP);
			}
			osInfo.setOsType(OSTYPE_WP);
			return osInfo;
		}
		// BlackBerry 黑莓系统判断
		String bbString = "BLACKBERRY";
		if (UA.indexOf(bbString) != -1) {
			rex = ".*" + bbString + "[\\s]*([\\d]*)";
			Pattern p = Pattern.compile(rex, Pattern.CASE_INSENSITIVE);
			Matcher m = p.matcher(UA);
			boolean rs = m.find();
			if (rs) {
				System.out.println("Mobil OS is" + " BLACKBERRY " + m.group(1));
				String version=m.group(1);
				osInfo.setVersion(version);
				osInfo.setOsTypeVersion(OSTYPE_BLACKBERRY+"_" + version);
			}else{
				System.out.println("BLACKBERRY");
				osInfo.setOsTypeVersion(OSTYPE_BLACKBERRY);
			}
			osInfo.setOsType(OSTYPE_BLACKBERRY);
			return osInfo;
		}
		if(UA.contains("LINUX")){//android
			if(isMatch(UA, "\\bMobi", Pattern.CASE_INSENSITIVE)){
				osInfo.setDeviceType(DEVICE_TYPE_PHONE);
			}else {
				osInfo.setDeviceType(DEVICE_TYPE_PAD);
			}
			
			 Pattern p = Pattern.compile("U;\\s*(Adr[\\s]*)?(\\d[\\.\\d]*\\d)[\\s]*;",Pattern.CASE_INSENSITIVE);
		        Matcher m = p.matcher(UA);
		        boolean result = m.find();
		        String find_result = null;
		        if (result)
		        {
		            find_result = m.group(2);
		        }
		        if(ValueWidget.isNullOrEmpty(find_result)){
		        	osInfo.setOsTypeVersion(OSTYPE_ANDROID);
		        	return osInfo;
		        }else{
		        	osInfo.setVersion(find_result);
		        	osInfo.setOsTypeVersion(OSTYPE_ANDROID+"_"+find_result);
		        	return osInfo;
		        }
		}
		
		//UCWEB/2.0 (iOS; U; iPh OS 4_3_2; zh-CN; iPh4)
		if(UA.matches(".*((IOS)|(iPAD)).*(IPH).*")){
			if(isMatch(UA, "[\\s]*iPh[\\s]*", Pattern.CASE_INSENSITIVE)){
				osInfo.setDeviceType(DEVICE_TYPE_PHONE);
			}else {
				osInfo.setDeviceType(DEVICE_TYPE_PAD);
			}
			 Pattern p = Pattern.compile("U;\\s*(IPH[\\s]*)?(OS[\\s]*)?(\\d[\\._\\d]*\\d)[\\s]*;",Pattern.CASE_INSENSITIVE);
		        Matcher m = p.matcher(UA);
		        boolean result = m.find();
		        String find_result = null;
		        if (result)
		        {
		            find_result = m.group(3);
		        }
		        if(ValueWidget.isNullOrEmpty(find_result)){
		        	osInfo.setOsTypeVersion(OSTYPE_IOS);
		        	osInfo.setOsType(OSTYPE_IOS);
		        	return osInfo;
		        }else{
		        	String version=find_result.replace("_", ".");
		        	osInfo.setVersion(version);
		        	osInfo.setOsTypeVersion(OSTYPE_IOS+"_"+version);
		        	osInfo.setOsType(OSTYPE_IOS);
		        	return osInfo;
		        }
		}
		return osInfo;
	}
	public static boolean isMatch(String source,String regx,int flags){
		Pattern p = Pattern.compile(regx,flags);
        Matcher m = p.matcher(source);
        boolean result = m.find();
        return result;
	}

}

 

应用场景:

 

通过user agent判断是否是手机

/***
	 * 判断是否是手机(移动端)
	 * @param userAgent
	 * @return
	 */
	public static boolean isMobile(String userAgent)
	{
		userAgent=userAgent.toLowerCase();
		String []mobile_agents = {"240x320","acer","acoon","acs-","abacho","ahong","airness","alcatel","amoi","android","anywhereyougo.com","applewebkit/525","applewebkit/532","asus","audio","au-mic","avantogo","becker","benq","bilbo","bird","blackberry","blazer","bleu","cdm-","compal","coolpad","danger","dbtel","dopod","elaine","eric","etouch","fly ","fly_","fly-","go.web","goodaccess","gradiente","grundig","haier","hedy","hitachi","htc","huawei","hutchison","inno","ipad","ipaq","ipod","jbrowser","kddi","kgt","kwc","lenovo","lg ","lg2","lg3","lg4","lg5","lg7","lg8","lg9","lg-","lge-","lge9","longcos","maemo","mercator","meridian","micromax","midp","mini","mitsu","mmm","mmp","mobi","mot-","moto","nec-","netfront","newgen","nexian","nf-browser","nintendo","nitro","nokia","nook","novarra","obigo","palm","panasonic","pantech","philips","phone","pg-","playstation","pocket","pt-","qc-","qtek","rover","sagem","sama","samu","sanyo","samsung","sch-","scooter","sec-","sendo","sgh-","sharp","siemens","sie-","softbank","sony","spice","sprint","spv","symbian","tablet","talkabout","tcl-","teleca","telit","tianyu","tim-","toshiba","tsm","up.browser","utec","utstar","verykool","virgin","vk-","voda","voxtel","vx","wap","wellco","wig browser","wii","windows ce","wireless","xda","xde","zte"};
		boolean is_mobile = false;
		for (String device : mobile_agents) {
			if(userAgent.contains(device)){
				is_mobile=true;
				break;
			}
		}
		return is_mobile;
	}

 测试代码:

@Test
	public void test_userAgent()
	{
		String userAgent="Mozilla/5.0 (Linux; U; Android 4.1.1; en-cn; HTC T528d) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 MicroMessenger/6.0.2.58_r984381.520 NetType/WIFI";
		System.out.println(HeaderUtil.isMobile(userAgent));
		
		userAgent="Opera/9.80 (Android 2.3.7; Linux; Opera Mobi/46154) Presto/2.11.355 Version/12.10";
		System.out.println(HeaderUtil.isMobile(userAgent));
	}

源代码见附件,工具类:com.common.util.HeaderUtil 

方法  getMobileOsInfo在com.common.util.WebServletUtil

 

判断微信

 public static boolean isMicromessengerBrowser(HttpServletRequest request) {
        String userAgent = request.getHeader("user-agent").toLowerCase();
        return userAgent.contains("micromessenger");
    }

 

 

作者:黄威 
主页:黄威的技术博客

 

 

  • 大小: 52.1 KB
  • 大小: 59.6 KB
0
1
分享到:
评论

相关推荐

    PHP判断访客是否手机端(移动端浏览器)访问的方法总结【4种方法】

    本文实例总结了PHP判断访客是否手机端(移动端浏览器)访问的方法。分享给大家供大家参考,具体如下: 在平常工作开发中,我们通常需要开发出PC端和移动端两个不同的系统,从而根据访问端的不同进入到不同的操作界面中...

    利用PHP判断是手机移动端还是PC端访问的函数示例

    在平常工作开发中,我们通常需要开发出PC端和移动端两个不同的系统,从而根据访问端的不同进入到不同的操作界面中。下面这篇文章主要给大家介绍了关于利用PHP判断是手机移动端还是PC端访问的函数的相关资料,需要的...

    PHP判断手机是IOS还是Android

    实例1:主要是要用到HTTP_USER_AGENT,它表示的意思是用来检查浏览页面的访问者在用什么操作系统(包括版本号)浏览器(包括版本号)和用户个人偏好的代码。 监测代码如下: function get_device_type() { //全部...

    网软志成PHP交友婚恋网站系统含手机WAP 3G触屏版 安卓手机客户端 苹果手机客户端 微软WP手机客户端等

    3、首页新增地区分站功能, 光明榜自动根据IP判断来源显示地区会员,点击选择,可自动出现二级城市按钮,匹配会员列表 4、新增我关注的人,会员可第一时间找到他(她)关注的交友对象 5、新增手机mini版交友 6、新增推广...

    OpenWBS 商城系统(手机 微信 PC 分销)X5.2.7.rar

    同一个数据库同一个后台管理,同一个域名网址实现手机端和PC端自动判断,手机访问即显示手机端,电脑访问即显示PC端。 OpenWBS 商城系统前台截图 OpenWBS后台管理 后台路径:域名/ow-admin/index.asp 用户名与密码...

    OpenWBS企业商城系统

    手机端微商城和PC端商城一体化,同一个数据库同一个后台管理,同一个域名网址实现手机端和PC端自动判断,手机访问即显示手机端,电脑访问即显示PC端。 OpenWBS企业商城系统 更新日志: X4.0 bulid161014 修复:...

    手机 pdf 阅读器

    [2009.1.1] Ver 3.2.26 ...申请了签名证书(在大多数NOKIA、SE手机上有效),请通过jad安装,没有数据线的请用手机访问http://www.ismyway.com/anyview.asp在线安装进行安装(请把读取用户数据/写入用户数据改为从不...

    FE内容付费系统响应式(带手机版) v4.65

    并支持3级下拉批量设置栏目下所有文章付费阅读,也可单独设置某篇文章付费阅读自动判断会员等级及积分,满足条件自动显示查看的内容。否则会根据等级或积分提示会员进行充值登录后自动跳转回原页面自动采集文章、...

    FE内容付费系统响应式v5.43 付费阅读文章+付费看图片+付费下载+付费视频播放+带手机版

    自动判断会员等级及积分,满足条件自动显示查看的内容。否则会根据等级或积分提示会员进行充值 登录后自动跳转回原页面 自动采集文章、自动发布文章、自动生成静态(高级功能) 自动定时发布(高级功能) 自动搜索...

    FE内容付费系统响应式(带手机版) v4.66.rar

    FE内容付费系统响应式(带手机版) v4.66 更新日志 优化多种格式音频加载的兼容性 FE内容付费系统程序特点 1、功能完善: 网站各种SEO属性设置、留言评论、会员投稿、会员积分功能、管理员管理、数据库备份还原、遍布...

    js如何判断用户是在PC端和还是移动端访问

    目前我们为“咖啡之翼”已经开发了移动终端以及安卓客户端,大家使用Android或者IOS操作系统的手机,直接访问域名www.sygxy.cn即可观看移动终端效果。同时Android客户端已经上架到腾讯“应用宝”和“百度手机助手”...

    H3BPM 试用系统操作手册

    4. 手机上的微信收到的消息推送界面,并可操作【驳回】、【提交】等操作。 3.5 业务集成 3.5.1 供应商入库/供应商获取 功能展示  通过业务服务(Data Table Adapter),写入、读取、更新第三方数据库(ERP)...

    ParkinglotAndroid:嵌入式物联网作品。智能自助式停车场管理系统,安卓手机端设计

    手机端不做权限的判断,比如说余额不足,未进入停车场操作等,这些处理都放到核心服务器那边处理,服务器处理完之后把相应的结果反馈给手机端,手机端再判断是否让用户操作,并给予提示。 手机端也不存储数据,数据...

    asp身份证批量查询与解读系统 v3.3

    更新记录支持手机电脑访问查询(同一个页面自适应),手机横屏横向表格,竖屏竖向表格,。20180330对身份证号的解读更为完善,比如原来一律只判断三十一天现在对30天的小月和二月的时间判断更为正确。20170411增加一...

    Google Android SDK开发范例大全(第3版) 1/5

    3.24 判断手机操作系统版本是否允许运行程序 3.25 两个不同的程序彼此调用 3.26 指定安装应用程序迁移至SD卡 3.27 手机动态Layout主题随手势物换迁移 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞 4.2 ...

    Google Android SDK开发范例大全(第3版) 4/5

    3.24 判断手机操作系统版本是否允许运行程序 3.25 两个不同的程序彼此调用 3.26 指定安装应用程序迁移至SD卡 3.27 手机动态Layout主题随手势物换迁移 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞 4.2 ...

    Google Android SDK开发范例大全(第3版) 3/5

    3.24 判断手机操作系统版本是否允许运行程序 3.25 两个不同的程序彼此调用 3.26 指定安装应用程序迁移至SD卡 3.27 手机动态Layout主题随手势物换迁移 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞 4.2 ...

    《Google Android SDK开发范例大全(第3版)》.pdf

    3.24 判断手机操作系统版本是否允许运行程序 72 3.25 两个不同的程序彼此调用 75 3.26 指定安装应用程序迁移至sd卡 78 3.27 手机动态layout主题随手势物换迁移 79 第4章 史上超豪华的手机控件 84 4.1...

Global site tag (gtag.js) - Google Analytics