使用 PHP、JavaScript 和 WURFL 的设备识别移动网站,第 1 部分: 开始使用 WURFL PHP API

不再为移动设备功能而迷茫

随着移动 Web 的快速发展,如果您还没有使用过 PHP 驱动的移动网站或应用程序,那么您很快就会用到。在数以千计的产品中检测一个移动设备的功能,仅使用 PHP 几乎是不可能实现的。但是有了 Wireless Universal Resource FiLe (WURFL) 之后,这个曾经令人生畏的艰巨任务变得像调用几个 API 来检索您需要的设备数据一样简单,并且可以与您的 PHP 站点和应用程序一起使用。

Chad Russell, 软件工程师兼顾问, 自由职业

Chad Russell 是一名软件工程师兼架构师,拥有 13 年的工作经验。他曾参与过从开发人员到软件架构师每个领域的工作,专攻于开源技术和基于 Web 的应用程序。由于主要关注 PHP、MySQL 和 JavaScript 技术,他有着广泛的行业经验,从小公司到世界 500 强。除了从事开发工作之外,他还是两本有关 MySQL 书籍的合著者。



2012 年 5 月 25 日

随着移动计算在其设备数量以及设备用户数量方面不断的增长,越来越多的移动仅有或移动特定网站和 Web 应用程序正在开发中。跟踪所有这些设备、设备的操作系统版本、每个设备的功能等等,都可能是一项艰巨的任务。现代移动浏览器结合了诸如 HTML5 和 CSS3 等新兴标准和技术,使专用设备少了许多后顾之忧。然而,很多特质仍然存在,而且可能永远存在于这些设备中,拥有这些信息为您所用,其价值将是无可估量的。

尽管一些基本的任务(比如,浏览器检测)可以使用 PHP 或者 JavaScript 轻易地完成,但是,在关于使用移动设备访问您的站点或应用程序的可能性方面仍然存在许多未知数。能够检测一个设备是否支持 Adobe® Flash®,检测该设备可以使用哪个 Ajax,或者检测它是否支持 CSS spriting,这些未必是您使用 PHP 或 JavaScript 可以快速确定的。

然而,使用 Wireless Universal Resource File(WURFL 发音为 “were-full”)可以轻松地调整您的移动站点和应用程序,因为您能确切地知道该设备可以做什么,不可以做什么。但如果没有 WURFL,这项任务的确是个挑战,但并不是不可能完成的。

WURFL 是什么?

从 WAP 到 WURFL

大约在 2001 年左右,最初的 Wireless Access Protocol (WAP) 电话上市几年之后,很明显,支持 WAP 的设备在处理 WAP 内容方面有很大差异。因此,两个富于创业精神的开发员(Luca Passani 和 Andrea Trasatti)走在一起构建了一个有关共享设备存储库的开源社区,他们将其称之为 WURFL。如今,10 年过去了,WURFL 也在不断增长,存储库中的设备数量以及提供的编程语言 API 都在不断增长。

WURFL 是一个由 ScientiaMobile 运行的开源 Device Description Repository (DDR) 项目,旨在成为移动设备信息的一个独立中央存储库。目前被 Facebook 和 Google 以及其他很多大小型企业所用。诸如有关正使用的移动浏览器的制造和版本信息、设备是否是平板,该设备是否能支持 Flash 等宝贵信息都可在 WURFL 中找到。

简单来说,WURFL 就是包含数千个移动设备及其各自功能的一个存储库。DDR 是由一个 XML 配置文件构成,搭配一组 API,这些 API 使您只需做少量的工作即可检索关于给定移动设备的海量信息。使用 WURFL PHP API,您就可以马上轻松地在您的移动 PHP 开发中使用 WURFL。


探索 WURFL

我们已经探讨了许多关于为什么使用 WURFL 以及它能实现什么的内容。现在我们来探讨一下 WURFL 中的数据是什么样的,以及使用它您有获得有关设备的何种信息。

在开始使用 DDR 和 WURFL PHP API 之前,您自己应该先熟悉一下 WURFL 中的数据类型。记住,WURFL 最简单的格式是一个 XML 文件:打开 WURFL 文件时,可以看到所有数据都在一组 XML 节点中组成。在 WURFL 文件中有许多节点,但是能找到有关给定移动设备的数据只有 3 个节点。表 1 显示了这些设备节点。

表 1. 主要 WURFL 设备节点
节点描述示例数据
<device>包含给定设备信息的主要节点<device id="htc_incredible_adr6300_ver1" user_agent="Mozilla/5.0 (Linux; U; Android 2.1-update1; en-us; ADR6300 Build/ERE27) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2" fall_back="generic_android_ver2_1" actual_device_root="true">
<group>设备节点的子节点;包含有关定义特性的信息<group id="display">
<capability>组节点的子节点;列出给定设备的各个功能,在某个给定组中指定。 <capability name="physical_screen_height" value="80"/>
<capability name="physical_screen_width" value="48"/>

从表 1 中,您可以确定每个设备的基本 XML 结构:

<device>
  <group>
    <capability />
    <capability />
    <capability />
  </group>
  <group>
    <capability />
    <capability />
    <capability />
  </group>
</device>

例如,如果您查看 WURFL 的内部,您会看到 Apple iPhone 4 设备的条目,如 清单 1 所示。

清单 1. iPhone 4 WURFL 条目
 <device id="apple_iphone_ver4" user_agent="Mozilla/5.0 (iPhone; U; 
 CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, 
 like Gecko) Mobile/7D11" fall_back="apple_iphone_ver3_1_3" 
 actual_device_root="true"> 
 <group id="product_info"> 
   <capability name="model_name" value="iPhone"/> 
   <capability name="device_os_version" value="4.0"/> 
   <capability name="model_extra_info" value="4.0"/> 
   <capability name="release_date" value="2010_april"/> 
 </group> 
 <group id="playback"> 
  <capability name="playback_acodec_aac" value="lc"/> 
  <capability name="playback_mp4" value="true"/> 
  <capability name="playback_3gpp" value="true"/> 
  <capability name="playback_acodec_amr" value="nb"/> 
  <capability name="playback_acodec_qcelp" value="false"/> 
  <capability name="playback_vcodec_mpeg4_sp" value="3"/> 
  <capability name="playback_vcodec_h263_0" value="30"/> 
  <capability name="playback_3g2" value="true"/> 
  <capability name="playback_vcodec_h264_bp" value="3.0"/> 
 </group> 
 <group id="streaming"> 
  <capability name="streaming_vcodec_h263_0" value="30"/> 
  <capability name="streaming_acodec_aac" value="lc"/> 
  <capability name="streaming_3gpp" value="true"/> 
  <capability name="streaming_vcodec_h264_bp" value="3.0"/> 
  <capability name="streaming_acodec_amr" value="nb"/> 
  <capability name="streaming_preferred_protocol" value="http"/> 
  <capability name="streaming_vcodec_mpeg4_sp" value="3"/> 
  <capability name="streaming_mp4" value="true"/> 
 </group> 
</device>

从该示例中,您可以看到,主设备节点中有 2 个子组节点为 iPhone 4 条目。这两个子节点提供关于该设备所支持的音频和视频编解码器的详细信息。但是等等,这里不应该包含更多信息吗,比如设备是否支持 Flash 或 PDF 或它是否是一个平板电脑?当然!实际上,您可以在 WURFL 中找到这些信息,但是由于 WURFL 的性质以及它在存储库已有设备信息上的构建方式,在这个条目中显然是没有这些信息的。

由于 WURFL 包含数千个设备规格以及每个设备各自的功能,所以它可以快速成为一个不断增长的复杂数据阵列,以继续进行构建和维护。然而,WURFL 的智慧体现在它管理这一复杂性的方法。

WURFL 的创建者已将有关移动设备的以下事实进行考量:

  • 尽管浏览器不同,但是有很多相同的特性。
  • 来自同一制造商的浏览器和设备总是从同一硬件和软件发展而来的。从对 Motion BlackBerry Curve 9350、9360 和 9370 的研究来看:它们之间的共性很多,并且差异非常小。
  • 来自不同制造商的设备可能运行相同的软件。例如,HTC、Motorola 和 Samsung 所有设备都运行 Google Android 操作系统,都有一个基于开源 WebKit 和 Google Chrome' 的 V8 JavaScript 引擎的浏览器。因此,在大多数情况下,每个设备就浏览器支持而言都是相似的。

把所有这些都纳入考量,能够降低 WURFL 的复杂性,并易于维护人员执行更新。本质上,WURFL 是基于一个设备系列的概念。如果您查看 WURFL 文件中的第一个设备,可以看到一个 ID 为 generic 的设备。WURFL 文件中的一切都是基于这个 generic 设备构建的。当添加一个新设备时,如果该设备属于既有设备系列,它将继承该系列的所有功能,除非该设备有特别的不同,与此同时,该信息会将被添加到给定设备中。

例如,如果您查看 清单 1 中 iPhone 4 示例 <device> 节点的 fall_back 属性,您会看到它引用了 apple_iphone_ver3_1_3(WURFL 中已有 iPhone 设备条目的设备 ID 属性)。如果您继续以此 ID 跟进,最终将会获得一个属性 ID 为 apple_iphone_ver1 的设备节点。沿着这个过程,您会找到更多的设备信息,比如它的首选地理定位 API、是否支持 Adobe Flash Light,以及显示分辨率。清单 2 提供了一些您将找到的组节点。

清单 2. 在 WURFL 找到的设备组
<group id="ajax"> 
   <capability name="ajax_preferred_geoloc_api" value="w3c_api"/> 
</group>
<group id="display"> 
   <capability name="resolution_height" value="480"/> 
   <capability name="resolution_width" value="320"/> 
</group>
<group id="flash_lite"> 
   <capability name="flash_lite_version" value=""/> 
   <capability name="fl_wallpaper" value="false"/> 
   <capability name="fl_browser" value="false"/> 
   <capability name="fl_screensaver" value="false"/> 
   <capability name="fl_standalone" value="false"/> 
   <capability name="fl_sub_lcd" value="false"/> 
</group>

设备

正如您在 iPhone4 WURFL 条目中所看到的,给定设备的每个规范以主 <device> 节点开始。这些节点通常包含用户代理字符串属性,一个 fall_back 设备属性,以及一个惟一的 ID 属性。

WURFL 包含了大量的数据组。这些数据组是设备节点的子节点,其中每个子节点均定义了一个设备可能支持或不支持的功能,以及有关在组节点中找到的功能的更多详细信息。您在 WURFL 中能找到的数据组有:product_infowml_uichtml_ui>xhtml_uihtml_uicssajaxmarkupcachedisplayimage_formatbugswtasecuritybearerstorageobject_downloadplaybackwap_pushdrmstreamingmmsj2mesmssound_formatflash_litetranscodingrsspdfchipssmarttvdeprecated

在 WURFL 帮助文档中找到最新的数据组列表以及每个数据组的完整描述(包含有关在给定组中定义的功能的表格分项,比如功能名称、类型和描述)(参见 参考资料 获取相关链接)。

功能

功能是其父组中定义的。所有功能名称属性均是惟一的,即使数据组之间也是惟一的,因此,在一个设备规范中功能名称不会多次出现。此外,功能都会有一个值,该功能值可以是布尔值、字符串(甚至是空字符串)或者数字。

清单 3 提供了您可以在 WURFL 中找到的实际组示例(包含其定义的功能)。

清单 3. WURFL product_info 组及其功能
 <group id="product_info"> 
  <capability name="pointing_method" value="touchscreen"/> 
  <capability name="uaprof" value="http://www.blackberry.net/go/mobile/
        profiles/uaprof/9500_edge/4.7.0.rdf"/> 
  <capability name="model_name" value="BlackBerry 9500"/> 
  <capability name="brand_name" value="RIM"/> 
  <capability name="model_extra_info" value="Thunder"/> 
  <capability name="marketing_name" value="Storm"/> 
</group>

在这里,您拥有最常见的组 product_info。正如您所看到的,您可以找到关于该设备的基本信息,比如模型和商标,以及此设备是否有触摸屏和用户代理配置文件。

另一个常见组是 display,如 清单 4 所示,提供关于设备屏幕尺寸和分辨率的详细信息。如果您想要在一个给定设备上正确显示一个移动网站或者 Web 应用程序,而不是全凭猜想,那么这些信息是非常有帮助的。

清单 4. 在 WURFL 中查找设备屏幕信息
<group id="display"> 
   <capability name="physical_screen_height" value="66"/> 
   <capability name="columns" value="36"/> 
   <capability name="dual_orientation" value="true"/> 
   <capability name="physical_screen_width" value="50"/> 
   <capability name="max_image_width" value="340"/> 
   <capability name="rows" value="32"/> 
   <capability name="resolution_width" value="360"/> 
   <capability name="resolution_height" value="480"/> 
   <capability name="max_image_height" value="440"/> 
</group>

有了这 2 个组,您就可看到,该设备支持 PDF 文档(见 清单 5),以及 Java™ 2 平台和 Mobile Edition (J2ME)。此外,您会再一次明白拥有这些信息是多么的重要,在您随意连接设备,不需要测试或者花费额外时间来编写代码来检查这些特性。

清单 5. 检查一个给定设备的 PDF 支持
<group id="pdf"> 
   <capability name="pdf_support" value="true"/> 
</group> 
<group id="j2me"> 
   <capability name="j2me_midp_2_0" value="true"/> 
   <capability name="j2me_cldc_1_0" value="true"/> 
   <capability name="j2me_cldc_1_1" value="true"/> 
   <capability name="j2me_midp_1_0" value="true"/> 
</group>

使用 PHP API

WURFL 项目中提供的 PHP API 使得您可以轻易地在 PHP 开发中使用 WURFL。(参见 参考资料 获取相关链接以下载 WURFL PHP API 最新版本。)以下简单的示例演示了如何快捷方便地检索一个给定移动设备的功能。

例如,您可以使用 getCapability 方法传入在 WURFL 中找到的一些不同的功能名称。您可以检索商标与型号名称,设备的分辨率,以及设备是否支持 PDF 和 Flash。该示例假设您已经下载 WURFL PHP API,并将其提取到 Web 服务器根目录中;您可以在 清单 6 中找到代码,在顶层 WURFL PHP API 目录下的 demo 目录中。

清单 6. PHP API 示例的 Demo 代码
<?php

define("WURFL_DIR", dirname(__FILE__) . '/../../WURFL/'); 
define("RESOURCES_DIR", dirname(__FILE__) . "/../resources/"); 

require_once WURFL_DIR . 'Application.php'; 

$wurflConfigFile = RESOURCES_DIR . 'wurfl-config.xml'; 

// Create WURFL Configuration from an XML config file 
$wurflConfig = new WURFL_Configuration_XmlConfig($wurflConfigFile); 

// Create a WURFL Manager Factory from the WURFL Configuration 
$wurflManagerFactory = new WURFL_WURFLManagerFactory($wurflConfig); 

// Create a WURFL Manager ($wurflManager is a WURFL_WURFLManager object) 
$wurflManager = $wurflManagerFactory->create();

获取最新的 WURFL 存储库

您可以在该项目的 SourceForge 页面中找到最新版本的 WURFL(参见 参考资料 获取相关链接)。一旦您在 PHP 应用程序中开始使用 DDR,就要确保您所使用的版本是最新的。更新 WURFL 很容易:只需要下载最新版本并替换已有的 wurfl.xml 文件即可。尽管批处理文件可用,但还是推荐替换现有的 wurfl.xml 文件。

首先,创建到 application.php 文件以及 WURFL XML 文件的相应路径。然后,创建 WURFL Manager 对象。检索特定设备信息的调用是从此对象检索获取的。

创建了 WURFL Manager 对象,就可以查询 WURFL 以获取几个数据片段,如 清单 7 所示。

清单 7. 查询数据的 WURFL
// This line detects the visiting device by looking at its HTTP Request ($_SERVER) 
$requestingDevice = $wurflManager->getDeviceForHttpRequest($_SERVER);

?> 

<html> 
 <body> 

  <ul> 
   <li>ID: 
    <?php echo $requestingDevice->id; ?> </li> 
     <li>Brand Name: 
          <?php echo $requestingDevice->getCapability("brand_name"); ?> </li> 
     <li>Model Name: 
          <?php echo $requestingDevice->getCapability("model_name"); ?> </li> 
     <li>Resolution Width: 
          <?php echo $requestingDevice->getCapability("resolution_width"); ?> </li> 
     <li>Resolution Height: 
          <?php echo $requestingDevice->getCapability("resolution_height"); ?> </li> 
     <li>PDF Support: 
          <?php echo $requestingDevice->getCapability("pdf_support"); ?> </li> 
     <li>Flash Support: 
          <?php echo $requestingDevice->getCapability("full_flash_support"); ?> </li> 
  </ul> 

 </body> 
</html>

当我从 iPhone 4 上加载此页面时,我看到了该设备的 ID,其制造与模型信息、屏幕信息以及是否支持 PDF 和 Flash。图 1 显示了加载结果。

图 1. iPhone 4 示例代码的结果
图像显示 iPhone 4 中的浏览器结果

从该示例,您可以看到为设备检索一个功能值,就和使用适当的功能名称调用 getCapability 方法一样简单。


结束语

从这篇文章中,您可以看到在您的移动网站或应用程序中使用 WURFL 有许多好处。简单便捷地收集有关给定设备的信息,而非投入大量时间编写额外的代码来获取无法得到的数据,是目前为止这个强大的 DDR 最吸引人的部分。

本系列第 2 部分将深入探讨 WURFL PHP API,并提供如何将其使用到您的移动 PHP 开发中的示例。

参考资料

学习

获得产品和技术

  • 下载 最新 WURFL 存储库
  • 下载 WURFL PHP API 最新版本
  • 下载并试用 IBM Mobile Technology Preview,一组代码样例和服务,可以帮助您开始构建可扩展和集成到企业中的移动应用程序。该预览包括一个 RESTful 通知服务;一个用于构建混合移动应用程序的开源框架 PhoneGap;一个轻量级的 WebSphere Application Server 运行时;以及向您演示其工作方式的样例代码。
  • IBM WebSphere Application Server Feature Pack for Web 2.0 and Mobile 包括 IBM Dojo 1.7 Toolkit、新的移动和富 Internet 应用程序 (RIA) 构建块,以及一个基于 Dojo 的图表组件。使用附带的 Rational 工具,该 Feature Pack 可帮助您采用原先面向桌面浏览器开发的 WebSphere 应用程序,对其进行调整,并将它们部署到移动设备中。
  • 以最适合您的方式 评估 IBM 产品:下载产品试用版,在线试用产品,在云环境下试用产品,或者在 SOA 沙盒 中花费几个小时来学习如何高效实现面向服务架构。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=移动开发, Open source, Web development
ArticleID=818352
ArticleTitle=使用 PHP、JavaScript 和 WURFL 的设备识别移动网站,第 1 部分: 开始使用 WURFL PHP API
publish-date=05252012