j2me与php使用xml为载体实现通信

October 23, 2009 – 6:35 pm

程序设计思路:j2me程序以http方式发送GET请求给服务器,服务器上的php程序返回xml格式的数据,j2me解析xml并处理数据。
备注:以下测试都基于模拟器,只是介绍实现思路,真机实现需要考虑的问题更多,例如http请求需要首先过滤中国移动的资费页面,汉字参数需要使用urlencode等等。

先解决几个问题:

问题一:为什么使用xml,而不是json?
解答:
php内置了处理json的方法,例如:

  1. <?php
  2. $array = array('key1' => array('value1' => 'hello'),
  3.                'key2' => array('value2' => 'world'));
  4. $array = json_encode($array);
  5. echo $array;
  6. //输出结果:{"key1":{"value1":"hello"},"key2":{"value2":"world"}}

j2me需要下载并导入包来实现json解析,首先从http://www.json.org上下载json me的包,解压缩到项目src目录中,开始写j2me代码:

  1. import org.json.me.*;
  2. /*
  3. * 测试j2me json 解析
  4. */
  5. public class testJson
  6. {
  7.     public static void main(String args[]) throws JSONException
  8.     {
  9.         System.out.println("---解析一般json键值对列---");
  10.         String s = "{'url':'http://www.baidu.com','left':'-98','top':'37'}";
  11.         JSONObject jsonString = new JSONObject(s);
  12.         System.out.println("url is " + jsonString.get("url"));
  13.         System.out.println("left is " + jsonString.get("left"));
  14.         System.out.println("top is " + jsonString.get("top"));
  15.        
  16.         System.out.println("---解析数组键值对---");
  17.         String arrayStr = "[{\"url\":\"www.baidu.com\",\"left\":\"-98\",\"top\":\"37\"},";
  18.         arrayStr += "{\"url\":\"www.google.com\",\"left\":\"98\",\"top\":\"37\"}]";
  19.         JSONArray jsonArray = new JSONArray(arrayStr);
  20.         int length = jsonArray.length();
  21.         System.out.println("数组长度是 " + length);
  22.         for(int i=0;i<length;i++)
  23.         {
  24.             JSONObject jsonArrayValue = jsonArray.getJSONObject(i);
  25.             System.out.println(jsonArrayValue);
  26.             System.out.println("url is " + jsonArrayValue.get("url"));
  27.             System.out.println("left is " + jsonArrayValue.get("left"));
  28.             System.out.println("top is " + jsonArrayValue.get("top"));
  29.         }
  30.     }
  31. }

由此可以看出,java操作的数组键值对json格式和php操作的json格式不同,而我们在实际传输中使用的大都是数组键值对的数据格式,所以json也就不适合作为二者web service通讯的数据格式了,同样在网络上搜索一下资料,j2me和php的通讯都在采用xml,而没有使用json。

问题二:是否需要使用urlencode或者urldecode处理字符串?
解答:
首先j2me没有内置urlencode方法,需要从j2se里抽取,那么是否有必要呢?如果GET参数中存在中文,就非常有必要。模拟器测试的时候可以不使用urlencode,但是在真机上,必须使用urlencode处理汉字参数。关于urlencode方法可以参考CSDN上的文章。

开始写代码:

解析xml使用KXml,从http://www.kxml.org下载kxml源代码,还要下载http://www.xmlpull.org上的xmlpull源代码,因为kxml继承了xmlpull类,然后把kxml和xmlpull的包拷贝到项目src目录下。kxml使用逐次读取xml的方式,消耗内存少,属于拉解析xml方式,适合j2me程序使用。
服务端php代码:

  1. <?php
  2. header('Content-Type:text/xml;Charset=utf-8;');
  3. $str = "<root><supplier><id>100</id><companyname>第一家</companyname><description>administrator欢迎光临</description></supplier><supplier><id>200</id><companyname>第二家</companyname><description></description></supplier></root>";
  4. echo $str;

j2me代码:

  1. /*
  2. * 使用http方式与服务器通讯,下载xml并解析
  3. *
  4. * heluan luanhelh@163.com
  5. */
  6. package httpXml;
  7.  
  8. import java.io.ByteArrayInputStream;
  9. import java.io.DataInputStream;
  10. import java.io.InputStreamReader;
  11. import javax.microedition.io.Connector;
  12. import javax.microedition.io.HttpConnection;
  13. import javax.microedition.lcdui.Display;
  14. import javax.microedition.lcdui.Form;
  15. import javax.microedition.midlet.MIDlet;
  16. import javax.microedition.midlet.MIDletStateChangeException;
  17.  
  18. import org.kxml2.io.*;//http://www.kxml.org
  19.  
  20. public class MIDlet1 extends MIDlet
  21. {
  22.     private Form frm = new Form("http方式与php通讯,解析xml");
  23.     private Display dis;
  24.     private String urlAddress = "http://localhost:80/test.php";
  25.     private String loadStr;
  26.     private String resultStr = "";
  27.     private String Supplier = "supplier";
  28.     private String supplierID = "id";
  29.     private String supplierName = "companyname";
  30.     private String supplierDesc = "description";
  31.    
  32.     protected void startApp() throws MIDletStateChangeException
  33.     {
  34.         dis = Display.getDisplay(this);
  35.         dis.setCurrent(frm);
  36.         loadStr = httpLoadString(urlAddress);
  37.         System.out.println("下载到的xml文档是:" + loadStr);
  38.         System.out.println("-----------------------------");
  39.         ByteArrayInputStream bin = new ByteArrayInputStream(loadStr.getBytes());
  40.         try
  41.         {
  42.             InputStreamReader reader = new InputStreamReader(bin);
  43.             KXmlParser parser = new KXmlParser();
  44.             boolean keepParsing = true;
  45.             parser.setInput(reader);
  46.             while (keepParsing)
  47.             {
  48.                 int type = parser.next();
  49.                 switch(type)
  50.                 {
  51.                 case KXmlParser.START_DOCUMENT:
  52.                     break;
  53.                 case KXmlParser.START_TAG:
  54.                     startElement(parser);
  55.                     break;
  56.                 case KXmlParser.END_TAG:
  57.                     break;
  58.                 case KXmlParser.TEXT:
  59.                     characters(parser);
  60.                     break;
  61.                 case KXmlParser.END_DOCUMENT:
  62.                     keepParsing = false;
  63.                     break;
  64.                 }
  65.             }
  66.         } catch (Exception e){}
  67.         System.out.println("-----------------------------");
  68.         System.out.println(resultStr);
  69.         frm.append(resultStr);
  70.     }
  71.    
  72.     public void startElement(KXmlParser parser) throws Exception
  73.     {
  74.         String xmlName = parser.getName();
  75.         System.out.println("startElement : " + xmlName);
  76.         if (xmlName.equals(Supplier))
  77.         {
  78.             resultStr += "商家 ";
  79.         }
  80.         else if (xmlName.equals(supplierID))
  81.         {
  82.             resultStr += "编号 ";
  83.         }
  84.         else if (xmlName.equals(supplierName))
  85.         {
  86.             resultStr += "商户名 ";
  87.         }
  88.         else if (xmlName.equals(supplierDesc))
  89.         {
  90.             resultStr += "商户描述 ";
  91.         }
  92.     }
  93.    
  94.     public void endElement(KXmlParser parser)
  95.     {
  96.         String xmlName = parser.getName();
  97.         System.out.println("endElement : " + xmlName);
  98.     }
  99.    
  100.     public void characters(KXmlParser parser)
  101.     {
  102.         String xmlText = parser.getText();
  103.         System.out.println("characters : " + xmlText);
  104.         resultStr += xmlText + " ";
  105.     }
  106.    
  107.     /*
  108.      * 发送http请求,GET方式
  109.      */
  110.     private static String httpLoadString(String url)
  111.     {
  112.         String str = "";
  113.         try
  114.         {
  115.             HttpConnection con = (HttpConnection)Connector.open(url);
  116.             DataInputStream dis = con.openDataInputStream();
  117.             int downLength = (int) con.getLength();
  118.             byte[] b = new byte[downLength];
  119.             dis.read(b);
  120.             str = new String(b);
  121.         }
  122.         catch (Exception ex)
  123.         {
  124.             ex.printStackTrace();
  125.         }
  126.         return str;
  127.     }
  128.    
  129.     protected void destroyApp(boolean arg0) throws MIDletStateChangeException{}
  130.     protected void pauseApp(){}
  131. }

编译运行结果如图所示:
j2me http xml
顺便再看一下以http方式发送汉字参数给服务器显示效果。
服务端php代码如下:

  1. <?php var_dump($_GET); ?>

j2me代码为:

  1. /**
  2. * 发送http的GET请求给服务器并返回结果
  3. * luanhelh@163.com
  4. */
  5. package http;
  6.  
  7. import java.io.DataInputStream;
  8.  
  9. import javax.microedition.io.Connector;
  10. import javax.microedition.io.HttpConnection;
  11. import javax.microedition.lcdui.Display;
  12. import javax.microedition.lcdui.Form;
  13. import javax.microedition.midlet.MIDlet;
  14. import javax.microedition.midlet.MIDletStateChangeException;
  15.  
  16. public class MIDlet1 extends MIDlet
  17. {
  18.     private Form frm  = new Form("测试http请求");
  19.     private Display dis;
  20.     private String callHttp = "http://localhost:80/test.php?title=你好MIDlet";
  21.    
  22.     protected void startApp() throws MIDletStateChangeException
  23.     {
  24.         dis = Display.getDisplay(this);
  25.         dis.setCurrent(frm);
  26.         String resultHttp = httpLoadString(callHttp);
  27.         System.out.println(resultHttp);
  28.         frm.append(resultHttp);
  29.     }
  30.    
  31.   /**
  32.      * 发送http请求,GET方式
  33.      */
  34.     private static String httpLoadString(String url)
  35.     {
  36.         String str = "";
  37.         try
  38.         {
  39.             HttpConnection con = (HttpConnection)Connector.open(url);
  40.             DataInputStream dis = con.openDataInputStream();
  41.             int downLength = (int) con.getLength();
  42.             byte[] b = new byte[downLength];
  43.             dis.read(b);
  44.             str = new String(b);
  45.         }
  46.         catch (Exception ex)
  47.         {
  48.             ex.printStackTrace();
  49.         }
  50.         return str;
  51.     }
  52.    
  53.     protected void destroyApp(boolean arg0) throws MIDletStateChangeException{}
  54.     protected void pauseApp(){}
  55. }

结果如图片所示:
j2me http GET

Post a Comment