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

我们现在做的项目,移动端和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

?

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

?

?

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。