j2me与php使用xml为载体实现通信
October 23, 2009 – 6:35 pm程序设计思路:j2me程序以http方式发送GET请求给服务器,服务器上的php程序返回xml格式的数据,j2me解析xml并处理数据。
备注:以下测试都基于模拟器,只是介绍实现思路,真机实现需要考虑的问题更多,例如http请求需要首先过滤中国移动的资费页面,汉字参数需要使用urlencode等等。
先解决几个问题:
问题一:为什么使用xml,而不是json?
解答:
php内置了处理json的方法,例如:
- <?php
- $array = array('key1' => array('value1' => 'hello'),
- 'key2' => array('value2' => 'world'));
- $array = json_encode($array);
- echo $array;
- //输出结果:{"key1":{"value1":"hello"},"key2":{"value2":"world"}}
j2me需要下载并导入包来实现json解析,首先从http://www.json.org上下载json me的包,解压缩到项目src目录中,开始写j2me代码:
- import org.json.me.*;
- /*
- * 测试j2me json 解析
- */
- public class testJson
- {
- public static void main(String args[]) throws JSONException
- {
- System.out.println("---解析一般json键值对列---");
- String s = "{'url':'http://www.baidu.com','left':'-98','top':'37'}";
- JSONObject jsonString = new JSONObject(s);
- System.out.println("url is " + jsonString.get("url"));
- System.out.println("left is " + jsonString.get("left"));
- System.out.println("top is " + jsonString.get("top"));
- System.out.println("---解析数组键值对---");
- String arrayStr = "[{\"url\":\"www.baidu.com\",\"left\":\"-98\",\"top\":\"37\"},";
- arrayStr += "{\"url\":\"www.google.com\",\"left\":\"98\",\"top\":\"37\"}]";
- JSONArray jsonArray = new JSONArray(arrayStr);
- int length = jsonArray.length();
- System.out.println("数组长度是 " + length);
- for(int i=0;i<length;i++)
- {
- JSONObject jsonArrayValue = jsonArray.getJSONObject(i);
- System.out.println(jsonArrayValue);
- System.out.println("url is " + jsonArrayValue.get("url"));
- System.out.println("left is " + jsonArrayValue.get("left"));
- System.out.println("top is " + jsonArrayValue.get("top"));
- }
- }
- }
由此可以看出,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代码:
- <?php
- header('Content-Type:text/xml;Charset=utf-8;');
- $str = "<root><supplier><id>100</id><companyname>第一家</companyname><description>administrator欢迎光临</description></supplier><supplier><id>200</id><companyname>第二家</companyname><description></description></supplier></root>";
- echo $str;
j2me代码:
- /*
- * 使用http方式与服务器通讯,下载xml并解析
- *
- * heluan luanhelh@163.com
- */
- package httpXml;
- import java.io.ByteArrayInputStream;
- import java.io.DataInputStream;
- import java.io.InputStreamReader;
- import javax.microedition.io.Connector;
- import javax.microedition.io.HttpConnection;
- import javax.microedition.lcdui.Display;
- import javax.microedition.lcdui.Form;
- import javax.microedition.midlet.MIDlet;
- import javax.microedition.midlet.MIDletStateChangeException;
- import org.kxml2.io.*;//http://www.kxml.org
- public class MIDlet1 extends MIDlet
- {
- private Form frm = new Form("http方式与php通讯,解析xml");
- private Display dis;
- private String urlAddress = "http://localhost:80/test.php";
- private String loadStr;
- private String resultStr = "";
- private String Supplier = "supplier";
- private String supplierID = "id";
- private String supplierName = "companyname";
- private String supplierDesc = "description";
- protected void startApp() throws MIDletStateChangeException
- {
- dis = Display.getDisplay(this);
- dis.setCurrent(frm);
- loadStr = httpLoadString(urlAddress);
- System.out.println("下载到的xml文档是:" + loadStr);
- System.out.println("-----------------------------");
- ByteArrayInputStream bin = new ByteArrayInputStream(loadStr.getBytes());
- try
- {
- InputStreamReader reader = new InputStreamReader(bin);
- KXmlParser parser = new KXmlParser();
- boolean keepParsing = true;
- parser.setInput(reader);
- while (keepParsing)
- {
- int type = parser.next();
- switch(type)
- {
- case KXmlParser.START_DOCUMENT:
- break;
- case KXmlParser.START_TAG:
- startElement(parser);
- break;
- case KXmlParser.END_TAG:
- break;
- case KXmlParser.TEXT:
- characters(parser);
- break;
- case KXmlParser.END_DOCUMENT:
- keepParsing = false;
- break;
- }
- }
- } catch (Exception e){}
- System.out.println("-----------------------------");
- System.out.println(resultStr);
- frm.append(resultStr);
- }
- public void startElement(KXmlParser parser) throws Exception
- {
- String xmlName = parser.getName();
- System.out.println("startElement : " + xmlName);
- if (xmlName.equals(Supplier))
- {
- resultStr += "商家 ";
- }
- else if (xmlName.equals(supplierID))
- {
- resultStr += "编号 ";
- }
- else if (xmlName.equals(supplierName))
- {
- resultStr += "商户名 ";
- }
- else if (xmlName.equals(supplierDesc))
- {
- resultStr += "商户描述 ";
- }
- }
- public void endElement(KXmlParser parser)
- {
- String xmlName = parser.getName();
- System.out.println("endElement : " + xmlName);
- }
- public void characters(KXmlParser parser)
- {
- String xmlText = parser.getText();
- System.out.println("characters : " + xmlText);
- resultStr += xmlText + " ";
- }
- /*
- * 发送http请求,GET方式
- */
- private static String httpLoadString(String url)
- {
- String str = "";
- try
- {
- HttpConnection con = (HttpConnection)Connector.open(url);
- DataInputStream dis = con.openDataInputStream();
- int downLength = (int) con.getLength();
- byte[] b = new byte[downLength];
- dis.read(b);
- str = new String(b);
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- }
- return str;
- }
- protected void destroyApp(boolean arg0) throws MIDletStateChangeException{}
- protected void pauseApp(){}
- }
编译运行结果如图所示:

顺便再看一下以http方式发送汉字参数给服务器显示效果。
服务端php代码如下:
- <?php var_dump($_GET); ?>
j2me代码为:
- /**
- * 发送http的GET请求给服务器并返回结果
- * luanhelh@163.com
- */
- package http;
- import java.io.DataInputStream;
- import javax.microedition.io.Connector;
- import javax.microedition.io.HttpConnection;
- import javax.microedition.lcdui.Display;
- import javax.microedition.lcdui.Form;
- import javax.microedition.midlet.MIDlet;
- import javax.microedition.midlet.MIDletStateChangeException;
- public class MIDlet1 extends MIDlet
- {
- private Form frm = new Form("测试http请求");
- private Display dis;
- private String callHttp = "http://localhost:80/test.php?title=你好MIDlet";
- protected void startApp() throws MIDletStateChangeException
- {
- dis = Display.getDisplay(this);
- dis.setCurrent(frm);
- String resultHttp = httpLoadString(callHttp);
- System.out.println(resultHttp);
- frm.append(resultHttp);
- }
- /**
- * 发送http请求,GET方式
- */
- private static String httpLoadString(String url)
- {
- String str = "";
- try
- {
- HttpConnection con = (HttpConnection)Connector.open(url);
- DataInputStream dis = con.openDataInputStream();
- int downLength = (int) con.getLength();
- byte[] b = new byte[downLength];
- dis.read(b);
- str = new String(b);
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- }
- return str;
- }
- protected void destroyApp(boolean arg0) throws MIDletStateChangeException{}
- protected void pauseApp(){}
- }
