今天突然心血来潮想写写关于j2me开发一些心的。
因为项目需要需要使用j2me开发,并且需要调用远程服务器,开始使用JSR 172开发,后来发现很多手机并不支持JSR 172,如果您是针对特定机型来开发并且那款机器支持JSR 172标准的话,恭喜你,我的教程您可以不用看了,因为用JSR 172开发超级简单。
好了回到正题,正式开始讲解。
首先说点废话,您需要下载、以及kxml2。
下载地址:http://downloads.sourceforge.net/ksoap2/ksoap2-j2me-core-2.1.2.jar?modtime=1173974533&big_mirror=0
http://downloads.sourceforge.net/kxml/kxml2-2.3.0.jar?modtime=1151079308&big_mirror=0
您可以去这里下载,下载好了导入你的工程即可。
剩下的当然就是代码啦。。。呵呵
由于我是直接从项目中拷贝出来的,所以一些细节东西我就不进行更改了
现在贴上核心代码:
String serviceNamespace = WebServiceUrl.URL + "service/SalesDataCollectionService";//WebServiceUrl.URL 这里面存放了一个具体的url地址便于 我调试使用,我的地址里面写的其实是 http://localhost:8080/ String serviceURL = WebServiceUrl.URL + "service/SalesDataCollectionService";//具体用处不是很大,因为和上面的地址是一样的,用上面的地址也是一样能跟完成的。 String methodName = "getXtm12ByXtwpdm";//调用的具体方法。这个方法需要传入一个参数,返回一个bean给用户。 SoapObject request = new SoapObject(serviceNamespace, methodName);//这里是一些准备工作,具体用处我就不多介绍了,因为我也不是很明白 request.addProperty( "xtwpdm",getTextFieldXtwpdm().getString());//这里是传入的参数,如果是多条参数就多复制几下就行了。他是一个键值对应的,其实也是按添加顺序来做的,你只要按照顺序往里面添加就行了,不过我的习惯是按照服务器端的名字对应填入键值。 SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);//类似于创建了一个连接工厂,因为我英语很烂,所以具体什么意思我也没弄明白,反正照着敲就不会错。 envelope.bodyOut = request;//将填入参数的request放入envelope 当中 (new MarshalBase64()).register(envelope);//需要做一下转码,其实用处不是很大,不过做总比不做好。要不不同的系统谁知道会出现什么问题呢。 HttpTransport ht = new HttpTransport(serviceURL);//创建连接了 ht.debug = true;//可以为false ht.call(null, envelope);//调用webservice了 if(envelope.getResponse()!=null){//判断是否返回结果,因为我这个是一个查询操作,是带有返回值的。byte[] bb = Base64.decode(envelope.getResponse().toString());将返回的结果进行转码,从string类型转换为byte[]数组,这个在后面我会介绍的,不要着急。 Xtm12Form xtm12 = Xtm12Form.deserialize(bb);//这个就是我们希望得到的那个bean。//bean的源码我会在后面公开的。 //既然得到的你要的bean了,剩下的就是你自己的事情了,自己该怎么向下进行都ok了。 //这个就是ksoap2的精华所在了。 }
下面给大家看看 我服务器端的代码
public byte[] getXtm12ByXtwpdm(String xtwpdm) { Xtm12 x = this.xtm12DAO.findById(xtwpdm);//得到我要的结果了 Xtm12Form xf = new Xtm12Form();//将结果进行了封装 xf.setKcjldw(x.getKcjldw());//因为涉及到商业机密,就简单的列出一个set方法了。 return xf.serialize();//返回是要求是byte[],所以我在bean中做了一下封装。 }
现在该看看精华了Xtm12Form bean 的源码,
package com.MobileRDA.FormBean; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import com.MobileRDA.StringVector; public class Xtm12Form { private String xtwpdm = ""; private StringVector wsvPersonName = new StringVector();//这就是进行二进制转换的类,我们将来在网络上传输的任何东西都是用二进制传输的,然后在将二进制转换回我们需要的东西。 public String getXtwpdm() { return xtwpdm; } public void setXtwpdm(String xtwpdm) { this.xtwpdm = xtwpdm; } public static Xtm12Form deserialize(byte[] data) {//将二进制还原为我们所需要的类 ByteArrayInputStream bais = new ByteArrayInputStream(data); DataInputStream dis = new DataInputStream(bais); Xtm12Form wc = new Xtm12Form(); try { wc.xtwpdm = dis.readUTF(); bais.close(); dis.close(); } catch (Exception exc) { // exc.printStackTrace(); } return wc; } public byte[] serialize() {//将我们的类转换为二进制便于网路传输。 ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); try { dos.writeUTF(xtwpdm); wsvPersonName.writeObject(dos); baos.close(); dos.close(); } catch (Exception exc) { // exc.printStackTrace(); } return baos.toByteArray(); } }
StringVector类的源码:
/** * Vector主要用来保存各种类型的对象(包括相同类型和不同类型的对象)。 * 但是在一些情况下使用会给程序带来性能上的影响。这主要是由Vector类的两个特点所决定的。 * 第一,Vector提供了线程的安全保护功能。即使Vector类中的许多方法同步。 * 但是如果你已经确认你的应用程序是单线程,这些方法的同步就完全不必要了。 * 第二,在Vector查找存储的各种对象时,常常要花很多的时间进行类型的匹配。 * 而当这些对象都是同一类型时,这些匹配就完全不必要了。 * 因此,有必要设计一个单线程的,保存特定类型对象的类或集合来替代Vector类 */ package com.MobileRDA; public class StringVector{ // 这儿的transient标示这个属性不需要自动序列化 private transient String[] data; private int count; public int size() { return count; } public StringVector() { // default size is 10 this(10); } public StringVector(int initialSize) { data = new String[initialSize]; } public void add(String str) { // ignore null strings if (str == null) { return; } ensureCapacity(count + 1); data[count++] = str; } private void ensureCapacity(int minCapacity) { int oldCapacity = data.length; if (minCapacity > oldCapacity) { String oldData[] = data; int newCapacity = oldCapacity * 2; data = new String[newCapacity]; System.arraycopy(oldData, 0, data, 0, count); } } public void remove(String str) { if (str == null) { return; // ignore null str } for (int i = 0; i < count; i++) { // check for a match if (data[i].equals(str)) { System.arraycopy(data, i + 1, data, i, count - 1); // copy data // allow previously valid array element be gc'd data[--count] = null; return; } } } public final String getStringAt(int index) { if (index < 0) { return null; } else if (index > count){ return null; // index is > # strings } else{ return data[index]; // index is good } } public synchronized void writeObject(java.io.DataOutputStream s) throws java.io.IOException { // Write out array length s.writeInt(count); // Write out all elements in the proper order. for (int i = 0; i < count; i++) { s.writeUTF(data[i]); } } public synchronized void readObject(java.io.DataInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in array length and allocate array int arrayLength = s.readInt(); data = new String[arrayLength]; // 同步data的大小 count = arrayLength; // Read in all elements in the proper order. for (int i = 0; i < arrayLength; i++) { data[i] = s.readUTF(); } } }
另外这个bean以及StringVector需要在服务器端和客户端都存在,不是一个单方面的。
好了,代码已经基本上写完了,剩下的就需要大家自己体会了。