Java 从用户代理字符串检测移动设备
我正在寻找一种方法来分析用户代理字符串,以确定它们是否由移动设备生成。这需要基于java,并可用于hadoop上的大批量日志文件分析,以生成统计数据(即,web服务不合适) 我看到了,但考虑到我只需要一个二进制移动/非移动响应,许可费似乎太高了 到目前为止,我一直在使用,这几乎正是我所需要的。然而,我遇到了一些限制。在我的测试中,我发现了许多用户代理字符串,这些字符串提供了足够的信息来确定用户代理来自移动设备,但被UADetector报告为未知 例如,标准化较差的Android应用程序可以发送UA字符串“Android”。这足以知道它来自移动设备,但UADetector将此UserAgentType报告为未知,而不是移动浏览器 's做了正确的事情,但我需要一些可以从Java中使用的东西Java 从用户代理字符串检测移动设备,java,user-agent,Java,User Agent,我正在寻找一种方法来分析用户代理字符串,以确定它们是否由移动设备生成。这需要基于java,并可用于hadoop上的大批量日志文件分析,以生成统计数据(即,web服务不合适) 我看到了,但考虑到我只需要一个二进制移动/非移动响应,许可费似乎太高了 到目前为止,我一直在使用,这几乎正是我所需要的。然而,我遇到了一些限制。在我的测试中,我发现了许多用户代理字符串,这些字符串提供了足够的信息来确定用户代理来自移动设备,但被UADetector报告为未知 例如,标准化较差的Android应用程序可以发送U
有谁能推荐一个更好的解决方案吗?如何读取JSP中的Apache Mobile筛选器值(对于Tomcat) 在必须配置mod_jk的httpd.conf文件中添加以下内容:
JkEnvVar AMF_IS_MOBILE undefined
Java代码是:
request.getAttribute("AMF_IS_MOBILE")
from:另一个线程建议使用以下库:
这似乎没问题。我是MobileESP项目的创始人和维护者,这是一个免费的开源跨平台库,用于检测移动设备。它还活着!:-) MobileESP只提供二进制“是移动的”响应。您可以通过iOS、Android或Windows Phone等平台进行检测,也可以通过“iPhone层”智能手机和平板电脑等设备类别进行检测。确保快速查看API页面 您可能知道,useragent字符串变化很大。如果设备上附带了浏览器,制造商可以对其进行自定义。例如,HTC经常定制本机Android浏览器的useragent字符串 谷歌提供了OEM如何定制useragent的建议。如果该设备应被视为手机,那么谷歌建议在字符串中包含单词“mobile”元素。但如果该设备应被视为平板电脑,则字符串不应包含“移动”。当然,遵守这一建议的情况差异很大 像Opera或Maxthon这样的第三方浏览器可以在useragent字符串中放入他们想要的任何内容——而且可以!某些无名的“新”浏览器在为每个平台(例如Android和iOS版本)的useragent字符串中添加正确信息方面做得很差。除非您从这些浏览器获得大量流量,并希望投资于跟踪每个平台和软件版本的用户代理确切值,否则您将无能为力 不管怎样,MobileESP的创建是为了在服务页面时逐页进行检测。我特意编写的代码也很容易阅读和定制 要进行批处理,可以执行以下操作: 1.)在构造函数中,注释掉initDeviceScan()方法。批量处理不需要这个 2.)将UserAgent和空字符串传入构造函数(UAgentInfo()) 3.)然后运行您感兴趣的任何检测方法。根据对用户的扫描,仔细考虑您为节省时间而执行这些操作的顺序 例如,如果您的大多数用户都在iPhone上,并且这是您感兴趣的检测标准之一,那么首先运行该检查。如果是这个示例,您肯定不会首先运行BlackBerry方法 我的联系信息在源代码和网站上。如果您有任何问题或遇到任何bug,请给我发一张便条。一定要在MobileESP.org网站上查找一些提示 祝你的项目顺利,安妮特
- 安东尼
Java
用户代理检测iPhone、Android和其他移动设备。如果您使用的是Spring,您可以根据需要自定义以下代码
@Override
public ModelAndView redirectToAppstore(HttpServletRequest request) {
String userAgent = request.getHeader("user-agent").toLowerCase();
String iphoneStoreUrl = "IPONE_STORE_URL";
String androidStoreUrl = "ANDROID_STORE_URL";
if (userAgent.contains("iphone"))
return new ModelAndView("redirect:" + iphoneStoreUrl);
else if (userAgent.contains("android"))
return new ModelAndView("redirect:" + androidStoreUrl);
return new ModelAndView("redirect:/");
}
51Degrees有一个免费的开源Java API,允许您运行脱机处理。您可以从GitHub存储库访问它
作为API的一部分,有一个脱机处理示例(代码如下所示),它获取用户代理的CSV文件,并将所需属性返回到输出文件中。下面的示例仅使用数据集中的3个属性,有关完整列表,您可以在此处查看字典
//当前工作目录中的输出文件
公共字符串outputFilePath=“批处理示例结果.csv”;
//模式检测匹配提供程序
私人最终提供者;
/**
*使用包含的Lite数据初始化设备检测提供程序
*文件。有关更多数据,请参阅:
*
*
*@如果读取数据文件时出现问题,则引发IOException。
*/
public OfflineProcessingExample()引发IOException{
提供程序=新提供程序(StreamFactory.create(
getLitePatternV32(),false));
}
/**
*读取包含用户代理的CSV文件并添加IsMobile,
*前20行的PlatformName和PlatformVersion信息。
*有关属性及其可用文件的完整列表,请
*见:
*
*@param inputFileName要从中读取的CSV文件。
*@param outputFilename保存带有额外条目的文件的位置。
*@如果读取数据文件时出现问题,则引发IOException。
*/
public void processCsv(字符串输入文件名、字符串输出文件名)
抛出IOException{
BufferedReader BufferedReader=
新的BufferedReader(新的文件读取器(inputFileName));
试一试{
FileWriter FileWriter=新的FileWriter(outputFilename);
试一试{
//从长远来看,创建匹配更有效
//一次并多次重复使用
// output file in current working directory
public String outputFilePath = "batch-processing-example-results.csv";
// pattern detection matching provider
private final Provider provider;
/**
* Initialises the device detection Provider with the included Lite data
* file. For more data see:
* <a href="https://51degrees.com/compare-data-options">compare data options
* </a>
*
* @throws IOException if there was a problem reading from the data file.
*/
public OfflineProcessingExample() throws IOException {
provider = new Provider(StreamFactory.create(
Shared.getLitePatternV32(), false));
}
/**
* Reads a CSV file containing User-Agents and adds the IsMobile,
* PlatformName and PlatformVersion information for the first 20 lines.
* For a full list of properties and the files they are available in please
* see: <a href="https://51degrees.com/resources/property-dictionary">
* Property Dictionary</a>
*
* @param inputFileName the CSV file to read from.
* @param outputFilename where to save the file with extra entries.
* @throws IOException if there was a problem reading from the data file.
*/
public void processCsv(String inputFileName, String outputFilename)
throws IOException {
BufferedReader bufferedReader =
new BufferedReader(new FileReader(inputFileName));
try {
FileWriter fileWriter = new FileWriter(outputFilename);
try {
// it's more efficient over the long haul to create a match
// once and reuse it in multiple matches
Match match = provider.createMatch();
// there are 20k lines in supplied file, we'll just do a couple
// of them!
for (int i = 0; i < 20; i++) {
// read next line
String userAgentString = bufferedReader.readLine();
// ask the provider to match the UA using match we created
provider.match(userAgentString, match);
// get some property values from the match
Values isMobile = match.getValues("IsMobile");
Values platformName = match.getValues("PlatformName");
Values platformVersion = match.getValues("PlatformVersion");
// write result to file
fileWriter.append("\"")
.append(userAgentString)
.append("\", ")
.append(getValueForDisplay(isMobile))
.append(", ")
.append(getValueForDisplay(platformName))
.append(", ")
.append(getValueForDisplay(platformVersion))
.append('\n')
.flush();
}
} finally {
fileWriter.close();
}
} finally {
bufferedReader.close();
}
}
/**
* Match values may be null. A helper method to get something displayable
* @param values a Values to render
* @return a non-null String
*/
protected String getValueForDisplay(Values values) {
return values == null ? "N/A": values.toString();
}
/**
* Closes the {@link fiftyone.mobile.detection.Dataset} by releasing data
* file readers and freeing the data file from locks. This method should
* only be used when the {@code Dataset} is no longer required, i.e. when
* device detection functionality is no longer required, or the data file
* needs to be freed.
*
* @throws IOException if there was a problem accessing the data file.
*/
@Override
public void close() throws IOException {
provider.dataSet.close();
}
/**
* Instantiates this class and starts
* {@link #processCsv(java.lang.String, java.lang.String)} with default
* parameters.
*
* @param args command line arguments.
* @throws IOException if there was a problem accessing the data file.
*/
public static void main(String[] args) throws IOException {
System.out.println("Starting Offline Processing Example");
OfflineProcessingExample offlineProcessingExample =
new OfflineProcessingExample();
try {
offlineProcessingExample.processCsv(Shared.getGoodUserAgentsFile(),
offlineProcessingExample.outputFilePath);
System.out.println("Output written to " +
offlineProcessingExample.outputFilePath);
} finally {
offlineProcessingExample.close();
}
}