SVG——新一代Web设计及互动媒体的革新

基于J2ME的SVGT移动手机应用

文章索引
基于J2ME的SVGT移动手机应用
2 什么是Mobile SVG标准
3 J2ME应用及其规范扩展
4 J2ME开发平台
5 JSR-226技术规范和应用
6 使用JSR-172解析XML数据
7 一个简单的SVG MIDP应用
8 Mobile SVG总结与参考资料
所有页面

基于J2ME的SVGT移动手机应用  本文首先介绍了矢量图形在移动领域中具有的优势,然后对其相关技术,包括Mobile SVG、J2ME以及JSR-226和JSR-172进行简单的介绍。最后,在以上技术的支持下,创建一个简单基于J2ME的SVGT网络监控应用。

来源:CSDN.NET

原链接:http://blog.csdn.net/firefight/archive/2007/02/15/1510618.aspx

1 矢量图形在移动应用上的优势

  矢量图形与光栅格式图像相比,在对动画、地图和互动图形进行编码和显示方面的优势是明显的。矢量图形是动态的、可以缩放的,能够描述非常高级的图形特性,如复杂形状、动画、分层图形和特殊效果等。

  利用矢量图形的缩放性,图形可以调整大小,以适应任何显示设备而不会导致品质损失。这在移动设备上是一个优势,因为移动设备的显示屏的形状、尺寸和分辨率差别很大。矢量图形还可以很方便的进行平移、缩放、旋转以及与用户交互的操作,因此用户可以在不影响图形质量的情况下对图形进行放大,这在使用手机的小屏幕看图时特别有用。

  矢量图形文件通常小于光栅图像文件,从而可以缩短无线下载时间,这点对于非常计较带宽的移动应用来说尤其重要。另外,将当前屏幕上的图形放大时,对于光栅图像会出现使图像模糊的马赛克效应,此时若要获得高质量的放大图像,则需重新从服务器获取放大后的图像,从而增加了网络的流量,而矢量图形在客户端进行放大就可以得到没有质量损失的放大图形。

  矢量图形的另一个强大功能是可以存储图形中各元素的相关信息。例如,通过对建筑矢量图形的附加数据,就可以知道房间的面积,售价等信息。

  最后,矢量图形可以方便的利用搜索引擎对图形中的属性进行搜索,实现基于图形的数据搜索。

  目前在移动领域的矢量应用主要包括FlashLite和Mobile SVG等,本文主要讨论Mobile SVG,关于SVG在移动设备中的优势你还可以阅读“基于移动设备的Mobile SVG的研究”一文了解更详细的内容。

图1 SVG在手机上的优势


  SVG(Scalable Vector Graphics,可升级矢量图形)是互联网联盟(W3C)的正式推荐标准,它是一种使用XML来描述二维图像的语言。由于SVG的大部分特性非常适合于无线领域的图形应用,为了满足移动业界的需求,W3C的SVG工作小组制订了适合于移动应用领域的Mobile SVG标准。

  Mobile SVG主要用于各种资源非常有限的移动设备,所以在实现Mobile SVG时,性能指标成为最主要的指标。由于移动设备在CPU速度、内存大小、支持的显示颜色等各个参数上有很大的不同,单一的专业标准很难满足所有移动设备的要求。因此,为了覆盖不同移动设备家族的需求,SVG工作小组最终制订了两个级别的Mobile SVG专业标准。一种专业标准是SVG Tiny (SVGT),适用于资源高度受限的移动设备,如手机;另一种专业标准是SVG Basic (SVGB),适用于高端的移动设备,如PDA等。由于移动设备硬件条件的限制,相对于标准的SVG,Mobile SVG在支持的内容、属性、功能等方面作了限制。SVGB是标准SVG的子集,而SVGT又是SVGB的子集,SVGT标准中删除了透明、渐变、裁剪、图案、符号和蒙板等复杂功能,而且没有对脚本支持。具体的不同请参考W3C SVG网址。

  以下是一个SVGT的例子:

<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     xmlns:demo="http://www.sun.com/svg/demo"
     id="root"
     width="100%" height="100%" viewBox="0 0 240 320"
     xml:space="preserve"
     preserveAspectRatio="none">
    <rect fill="#35556B" width="240" height="320"/>
    <g id="processingIndicator" transform="translate(120, 97) scale(0.5)" >
       <g id="processingIndicator.outerCircle">
              <path transform="translate(-120, -97)" fill="#C1CBD1" d="M73.426,97.169c0,25.681,20.894,46.575,46.575,46.575c25.681,0,46.574-20.894,46.574-46.575c0-9.251-2.708-18.192-7.83-25.854c-1.688-2.525-5.104-3.204-7.629-1.516s-3.204,5.104-1.516,7.629c3.908,5.847,5.975,12.673,5.975,19.741c0,19.616-15.959,35.575-35.574,35.575c-19.616,0-35.575-15.958-35.575-35.575c0-19.616,15.959-35.575,35.575-35.575c6.063,0,12.048,1.551,17.307,4.485c2.652,1.48,6.002,0.53,7.482-2.123c1.48-2.653,0.529-6.003-2.123-7.483c-6.893-3.846-14.73-5.879-22.666-5.879C94.319,50.594,73.426,71.488,73.426,97.169z"/>
       </g>
       <g id="processingIndicator.innerCircle">
              <path transform="translate(-120, -97)" fill="#738999" d="M120.001,69.772c-5.441,0-10.701,1.592-15.21,4.607c-2.525,1.688-3.204,5.104-1.516,7.629c1.688,2.525,5.104,3.204,7.629,1.516c2.693-1.8,5.838-2.752,9.096-2.751c4.38,0,8.498,1.705,11.594,4.802c3.098,3.097,4.803,7.214,4.803,11.594c0,9.042-7.355,16.397-16.397,16.397c-9.041,0-16.396-7.355-16.396-16.397l0.065-1.479c0.134-3.034-2.201-5.848-5.236-5.981c-3.034-0.134-5.587,1.972-5.721,5.007l-0.108,2.454c0,15.107,12.29,27.397,27.396,27.397c15.107,0,27.397-12.291,27.397-27.397c0-7.318-2.85-14.198-8.024-19.373S127.318,69.772,120.001,69.772z"/>
       </g>
       <g id="processingIndicator.center" >
              <circle fill="white" transform="translate(-120, -97)" cx="120" cy="97.169" r="9.349"/>
              <circle display="none" fill="#35556B" transform="translate(-120, -97)" cx="122.321" cy="92.551" r="2.078"/>
       </g>
    </g>
    <defs>
            <animateTransform id="processingIndicatorAnim" xlink:href="#processingIndicator.innerCircle" attributeName="transform" type="rotate" values="0;360" begin="0s" dur="3s" repeatDur="indefinite"/>
            <animateTransform xlink:href="#processingIndicator.outerCircle" attributeName="transform" type="rotate" values="0;-360" begin="0s" dur="2s" repeatDur="indefinite"/>
            <animateTransform xlink:href="#processingIndicator.center" attributeName="transform" type="rotate" values="0;-360" begin="0s" dur="1s" repeatDur="indefinite"/>
    </defs>
<g id="loadProgressBar">
        <rect id="loadProgressBar.bkg" fill="#A3B8CB" x="45" y="250" width="150" height="10" />
        <rect id="loadProgressBar.progress" fill="white" x="45" y="250" width="20" height="10" />
        <text transform="translate(120,230)" fill="#BDBEC0" font-size="12" text-anchor="middle">loading application</text>   
        <text id="loadProgressBar.text" text-anchor="middle" transform="translate(120,275)" fill="#FFFFFF" font-size="12">0%</text>
</g>
</svg>

  Mobile SVG最近已被3GPP组织所采纳,用于多媒体短信服务(MMS)。Mobile SVG将很快应用在许多2.5G和3G MMS服务中。Mobile SVG的增强MMS短信功能对于手机制造商具有明显的吸引力。与运营商一样,OEM厂商也可以在不对设计作重大变动或不显著增加成本的情况下,增加Mobile SVG功能。由于Mobile SVG是内容丰富的通用平台,最适合于帮助设备制造商提供差别化服务。

  为了实现SVGT在手机上的应用,开发人员需要了解手机开发平台及其对SVGT的支持情况,其中最常见的是基于JAVA语言的J2ME移动开发平台。

  比如应用J2ME及SVG构造手机LBS系统,系统融合GIS与无线通信、J2ME及SVG,以J2ME为开发平台,结合空间数据以SVG为地图显示介质,在手机中实现方便、快捷、精确的移动位置服务,关于这节内容大家可以通过“3G移动位置服务系统的设计与实现”一文获得了解 。


  随着移动技术的发展,手机已经从最初的一种单纯的通信工具转变成如今集通信、工作、娱乐等功能为一体的综合设备。因此,在移动终端上开发通用的、丰富的应用已成为必然的趋势。这些应用能够提供与桌面应用相媲美的功能,并可以按用户的意愿随时安装和删除。然而手机平台在硬件,操作系统等系统底层有很大的不同,给应用程序的开发带来了很大的困难,开发人员迫切需要一种通用的开发平台。

  J2ME(JAVA2 Micro Edition)正是这样一种JAVA应用开发平台。实际上,JAVA语言从其诞生起就以其运行的平台无关性这一强大的优势而成为网络应用的宠儿。J2ME是JAVA2标准版本的微型版本,专门为小型移动设备所设计。这些设备处理器的处理能力都不强,可使用的资源也有限。因此,J2ME只包含了J2SE中在移动通信设备上所必需的功能和组件,使其能够在移动设备及其有限的资源上开发出丰富多彩且平台无关的应用。J2ME在结构上分为CDC(Connected Device Configuration)和相应的Foundation Profile规范,以及CLDC(Connected Limited Device Configuration)和相应的MIDP规范。

  MIDP(Mobile Information Device Profile)是移动信息设备规范的简称,规范具体定义了J2ME适用的硬件和软件框架,并提供了这个框架要实现的基本功能及其标准接口,应用开发者可以基于这个框架开发出各种应用。2000年9月,SUN公司发布了MIDP的第一个正式版本MIDP1.0。它将J2ME适用的设备定位在至少拥有数百KB RAM和ROM,并具有基本网络和显示功能的移动通信设备上。在该基础上定义了一系列软件接口,其中包括基本输入输出、图形化用户接口(GUI)、网络、事件机制、文件系统、应用管理系统(AMS)等。之后,随着JAVA技术的不断发展和用户需求的不断提高,SUN公司又于2002年11月发布了MIDP2.0。它对设备的内存资源和处理能力的要求较1.0要高,但也为应用开发者提供了更方便、更丰富多彩的软件包。MIDP2.0中主要增加了游戏接口的实现、声音输出接口的实现安全网络机制的实现。MIDP2.0的这些特性将使基于移动设备的JAVA应用具有更加广阔的前景,也必将使新一代的移动设备发生革命性的变化并领导时尚潮流。

  另外,为了支持不同的应用方向,SUN还联合其它一些公司共同制定了J2ME扩展技术规范,包括图形应用、网络服务、多媒体和安全等。其中本文中主要使用到移动2D SVG图形方面的JSR-226和WEB服务方面的JSR-172。

  所有MIDP应用从MIDlet类中派生,MIDlet类管理和控制着应用程序的生命周期,包括装载、激活、暂停和销毁四个阶段。当设备装入MIDlet并调用其构造函数时为装载期,直到程序管理器调用应用程序的startApp()方法。在startApp()调用后,应用程序处于激活期,直到调用了pauseApp()或destroyApp()。pauseApp()暂停应用程序,而destroyApp()销毁应用程序。一个典型的MIDlet代码如下:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Hello extends MIDlet
{
private Display display;
public Hello()
{
display = Display.getDisplay(this);
}
public void startApp()
{
Form f = new Form("Test");
f.append("hello world!");
display.setCurrent(f);
}
public void pauseApp()
{
}
public void destroyApp(boolean unconditional)
{
}
}


  开发人员可以在SUN的J2ME网址上下载CLDC移动开发工具,目前的最新版本为2.5。

  Sun Java™ Wireless Toolkit 2.5X新增了一个新的平台,移动服务架构(JSR 248以及9个新的可选API包,其中包括:)

  • Security and Trust Services APIs for J2ME (JSR 177支持智能卡访问和数据加密功能,包括创建和签署证书。)
  • Location API for J2ME (JSR 179提供与GPS等位置服务硬件交互功能。)
  • SIP API for J2ME (JSR 180实现了建立多媒体会话使用的标准会话启用协议(Session Initiation Protocol)。)
  • Content Handler API (JSR 211提供内容处理机制,当接收到特定媒体类型的内容时自动启用相关的处理器。)
  • Scalable 2D Vector Graphics API for J2ME (JSR 226提供了显示和渲染SVG内容的API。 )
  • Payment API (JSR 229为应用程序提供了标准的支付方式。)
  • Advanced Multimedia Supplements (JSR 234在 Mobile Media API (JSR 135的基础上进行扩展,提供了3D音频,音频特效和照相支持。))
  • Mobile Internationalization API (JSR 238为多语言应用程序定义了资源文件机制。)
  • Java Binding for the OpenGL® ES API (JSR 239为OpenGL® for Embedded Systems (OpenGL® ES) 和 EGL 的API提供了JAVA语言的绑定。OpenGL® ES为3D图形的标准API, EGL为标准的平台接口层。二者都是Khronos Group (http://khronos.org/opengles/开发的。 ))

   开发工具中带有丰富的示例,便于开发人员的了解和学习。


  JSR-226的定义了SVG 图形(Mobile 2D Graphics,M2G)API。其中SVG矢量图形是ScalableImage的实例,你可以通过静态的createImage()方法获得它们。 SVGImage是ScalableImage的一个子类,它提供事件处理和底层DOM文档访问之间的联系。大多数情况下我们会使用这个类。例如如何从一个SVGT文件中创建一个SVGImage实例:

try{
InputStream imageStream = getClass().getResourceAsStream("/loadScreen.svg");
SVGImage svgImage = (SVGImage)SVGImage.createImage(imageStream, null);
} catch(Exception e) {
    e.printStackTrace();
}

  然后,创建ScalableGraphics的一个实例:

ScalableGraphics sg = ScalableGraphics.createInstance();

  最后,在paint事件中显示SVG图形:

public void paint(Graphics g) {
       // *** clear the display
       g.setColor(255, 255, 255);
       g.fillRect(0, 0, getWidth(), getHeight());
       // *** render the SVG image
      sg.bindTarget(g);
       sg.setTransparency(1f);
        svgImage.setViewportWidth(getWidth());
        svgImage.setViewportHeight(getHeight());
        sg.render(0, 0, svgImage);
        sg.releaseTarget();
}

  为了使渲染动画SVG 内容的普通情况更加方便,JSR-226还提供了SVGAnimator类。通过SVGAnimator可以创建和控制一个Canvas对象,这个对象自动处理屏幕更新,以播放动画事件和相应用户的操作。因此使用SVGAnimator不需要显式创建ScalableGraphics对象。例如:

try{
             InputStream imageStream = SVGMobile.class.getResourceAsStream("/Halloween.svg");
             svgImage = (SVGImage)SVGImage.createImage(imageStream, null);
             svgAnimator = SVGAnimator.createAnimator(svgImage);
     }
     catch(Exception e) {
         e.printStackTrace();
     }
       
       // Set to 10 fps (frames per second)
       svgAnimator.setTimeIncrement(0.01f);
 
       svgCanvas = (Canvas)svgAnimator.getTargetComponent();
       svgImage.setViewportWidth(svgCanvas.getWidth());
       svgImage.setViewportHeight(svgCanvas.getHeight());
      
       // The SVG root element is used to reset the time on a stop operation.
       doc = svgImage.getDocument();
       svg = (SVGSVGElement)doc.getDocumentElement();
      
       svgCanvas.setCommandListener(this);
       // Hook-in key listeners to play, pause and stop the animation.
       svgAnimator.setSVGEventListener(this);
      
       svgAnimator.play();
       state = STATE_PLAYING;
       System.err.println("PLAYING...");
              
// *** grab a reference to the display
       display = Display.getDisplay(this);
       display.setCurrent(svgCanvas);
      
       // *** set up the midlet menu
       int hotKey = 0;
       svgCanvas.addCommand(exitCommand);

  在应用程序中,不仅可以从SVG文档装载静态的SVG数据,而且可以创建空的SVGImage,然后通过操作其DOM数据形成需要的图形,下例中创建了一个空SVGImage,然后在DOM树中追加了一个SVG text元素。

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.m2g.ScalableGraphics;
import javax.microedition.m2g.SVGImage;
import org.w3c.dom.Document;
import org.w3c.dom.svg.SVGElement;
import org.w3c.dom.svg.SVGSVGElement;
import org.w3c.dom.svg.SVGRGBColor;

public class HelloSVG extends MIDlet  {
 
  protected SVGImageCanvas svgCanvas = null;
  public HelloSVG() {
 
  }
  public void startApp() {
    SVGImage svgImage = SVGImage.createEmptyImage(null);
    Document doc = svgImage.getDocument();
    SVGSVGElement svg = (SVGSVGElement) doc.getDocumentElement();
    SVGElement textElement = (SVGElement) doc.createElementNS("http://www.w3.org/2000/svg", "text"); 
    textElement.setTrait("#text", "Hello JSR-226 !");
    textElement.setFloatTrait("x", 50.0f);
    textElement.setFloatTrait("y", 50.0f);
    SVGRGBColor textColor = svg.createSVGRGBColor(0, 0, 0);
    textElement.setRGBColorTrait( "stroke", textColor);
    svg.appendChild(textElement);
    svgCanvas = new SVGImageCanvas(svgImage);
    Display.getDisplay(this).setCurrent(svgCanvas);
  }
   public void pauseApp() {
   }
    public void destroyApp(boolean unconditional) {
    }
}
class SVGImageCanvas extends Canvas {
    protected SVGImage svgImage;
    protected ScalableGraphics sg = ScalableGraphics.createInstance();

    protected SVGImageCanvas(final SVGImage svgImage) {
        this.svgImage = svgImage;
    }
public void paint(Graphics g) {
        g.setColor(255, 255, 255);
        g.fillRect(0, 0, getWidth(), getHeight());
        sg.bindTarget(g);
        svgImage.setViewportWidth(getWidth());
        svgImage.setViewportHeight(getHeight());
        sg.render(0, 0, svgImage);
        sg.releaseTarget();
    }
}

  这些类都定义在javax.miroedition.m2g和org.w3c.dom.svg包中,更多内容请参考JSR-226的技术规范文档。SVG DOM是在org.w3c.dom和org.w3c.dom.events包中定义的。

  使用SVG 不可避免的要涉及XML的解析和使用。JSR-172是J2ME下访问WEB服务的标准API,提供了一个标准的轻量级XML解析器。JSR-172实现了JAXP1.2(Java API for XML Processing)的一个子集,支持SAX2.0。在JSR-172中使用SAX方式处理XML数据,相比DOM的处理方式更加节省内存,因此在同样的硬件条件下,SAX能够处理更大的XML文档或数据。JSR-172中包括3个包,其中javax.xml.parsers 包括SAX解析器,工厂和异常类;org.xml.sax中包括核心SAX API;org.xml.sax.helpers中包括多种辅助类。

  此外 ,用户还可以使用KXML等XML解析器在J2ME应用程序中处理XML数据,尤其是在平台不支持JSR-172的时候。

  以下是使用SAX解析XML的具体实例,其中省略了一些代码。首先创建SAX处理器类。

class BasicHandler extends DefaultHandler
{
private Stack tagStack = new Stack();
public BasicHandler (){}
public void startDocument() throws SAXException {}
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException  {
    if(qName.equals("AAA")) { /*数据处理*/}
    tagStack.push(qName);
  }
public void characters(char[] ch, int start, int length) throws SAXException {
    String chars = new String(ch, start, length).trim();
    if(chars.length() > 0){
      String qName = (String)tagStack.peek();
      if (qName.equals("BBB")) { /*数据处理*/}
}
}
public void endElement(String uri, String localName, String qName, Attributes attributes) throws SAXException  {
    tagStack.pop();
  }
  public void endDocument() throws SAXException   { }
}

  之后装入一个XML文件并指定为此前定义的SAX处理器。

try
{
  SAXParserFactory factory = SAXParserFactory.newInstance();
  SAXParser saxParser = factory.newSAXParser();
  FileConnection fc = (FileConnection) Connector.open("file:///root1/phones.xml");
  InputStream is = fc.openInputStream();
  InputSource inputSource = new InputSource(is);
  saxParser.parse(is,new BasicHandler(this));
}
catch(Exception ex) {}

  我们也可以从一个输入流中加载XML,例如从一个XML字符串:

InputStream is = new ByteArrayInputStream(xmlString.getBytes(), 0, xmlString.length());
InputSource inputSource = new InputSource(is);
saxParser.parse(is,new BasicHandler(svgCanvas));


  现在我们可以将上面提到的技术组合起来,形成一个完整基于手机短信的网络监控应用,功能是根据短信数据显示当前的网络状态。类图如下:

图2 基于手机短信的网络监控应用的类图

   其中MySamplePushRegistry为一个MIDP应用,启动后显示界面为一个SvgCanvas类对象,并在在50001端口启动SMS侦听。SvgCanvas为SVG窗口类,负责显示SVG内容,这些内容来自一个定义好的SVG文件,这里为一个简单的网络图,包括一个PC机,一台打印机以及之间的网络连接。BasicHandler为SAX解析处理器,Status类为短信数据类。

  应用程序的基本流程为:MIDP启动后显示SVG文件,并启动在SMS特定端口侦听;在接收到XML短信数据后,MIDP使用BasicHandler解析XML,生成状态对象并存入对象列表;在解析结束后,通知 SvgCanvas将根据状态对象更新显示界面,在故障情况下将相应部件颜色改为红色,正常情况则为绿色。

  应用程序在模拟器中运行的情况如下:

  1, 启动画面

图3 MIDP在模拟器中的启动画面

   2, 发送XML数据短信

图4 发送XML数据短信


  3,PC正常,与打印机连接故障和打印机故障的情况显示

图5 发送XML数据短信


  Mobile SVG已开始在MMS上显露身手,但实际上除了MMS,Mobile SVG还有丰富的应用,其中包括:
娱乐教育等,包括各种手机游戏和在线教程等。
基于位置的服务,在地图上显示运动物体及相关链接,同时允许用户缩放地图、切换不同图层的可见性、选择特定的区域等。具体应用如汽车导航、汽车调度、电子导游、移动广告等。
现场服务:包括技术制图,设备监控等,借助于Mobile SVG,就可以绘制出前后一致的、高品质的图像,可以看全景,也可以看局部细节。
其它任何JPG、GIF或其它位图格式不能满足要求的无线应用场合,如要求提供内容丰富、可伸缩、互动的图形或动画的地方。
 
  对于下一代无线系统(3G)来说,是否能够成功取决于用户的需求。对于无线用户来说,如果存在更加吸引他们的应用,他们就会更换现有的手机。经由像 Mobile SVG这样以用户为中心的技术增强的MMS,将会产生更多促使手机升级的充分的理由。所以,对于业界来说,其面对的挑战是实现和应用Mobile SVG或其它矢量应用,例如FlashLite等。总的来说,在实现Mobile SVG的过程中,需要运营商、终端制造商、内容提供商共同努力,才能使Mobile SVG的无限魅力在资源受限的移动设备上大放光彩。
 
  Mobile SVG相关参考资料:

(THE END)

 

将要更新