J2ME无线联网技术
首先看一下GCF框架体系,如下图所示:
CLDC只是定义了基于底层通信协议(如传输流或数据报等)的网络连接中的一些接口定义,至于具体某种高层协议
的网络连接一般在简表中定义,因为不同的设备支持的高层网络通信协议是不一样的,因此完全没必要在CLDC配置中来定义。
在专门针对移动信息设备的MIDP简表中,定义了ServerSocketConnection、SocketConnection、UDPDatagramConnection和HttpConnection接口来提供对高层网络协议的网络通信进行支持。其中HttpConnection是MIDP规定设备必须支持的。
因此,可以总结出我们需要掌握的方面:使用Http连接Internet、开发Socket网络连接应用、开发Datagram网络连接应用,下面着重讲解前两种。
1.使用Http连接Internet
我写了一个使用Http从http://life.yule.com.cn/UploadPic/2008-1/200814142026328.jpg下载并显示图片的例子。代码如下:
import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import javax.microedition.io.*; import java.io.*; public class ViewImage extends MIDlet implements CommandListener{ private Display dis; private TextBox tbMain; private Alert alStatus; private Form fm; private Command cmExit; private Command cmView; private Command cmBack; private static final int ALERT_DISPLAY_TIME =3000; Image im=null; public ViewImage() { // TODO Auto-generated constructor stub dis=Display.getDisplay(this); tbMain=new TextBox("输入图片地址","http://life.yule.com.cn/UploadPic/2008-1/200814142026328.jpg",75,0); cmExit=new Command("退出",Command.EXIT,1); cmView=new Command("下载",Command.SCREEN,2); tbMain.addCommand(cmExit); tbMain.addCommand(cmView); tbMain.setCommandListener(this); fm=new Form(""); cmBack=new Command("后退",Command.BACK,1); fm.addCommand(cmBack); fm.setCommandListener(this); } protected void destroyApp(boolean arg0) throws MIDletStateChangeException { // TODO Auto-generated method stub } protected void pauseApp() { // TODO Auto-generated method stub } protected void startApp() throws MIDletStateChangeException { // TODO Auto-generated method stub dis.setCurrent(tbMain); } public void commandAction(Command c,Displayable s) { if(c==cmExit) { try{ destroyApp(false); notifyDestroyed(); }catch(Exception e){ } }else if(c==cmView) { showAlert("下载中",false,tbMain); Thread dl=new Download(tbMain.getString(),this); dl.start(); } else if(c==cmBack) { dis.setCurrent(tbMain); } } public void showImage(boolean flag) { if(flag==false) { showAlert("下载失败",true,tbMain); } else { ImageItem ii=new ImageItem(null,im,ImageItem.LAYOUT_CENTER,null); if(fm.size()!=0) fm.set(0, ii); else fm.append(ii); showAlert("下载成功",true,fm); } } public void showAlert(String msg,boolean modal,Displayable displayable) { alStatus=new Alert("状态",msg,null,AlertType.INFO); if(modal) { alStatus.setTimeout(Alert.FOREVER); } else { alStatus.setTimeout(ALERT_DISPLAY_TIME); } dis.setCurrent(alStatus, displayable); } class Download extends Thread { private String url; private ViewImage Midlet; private boolean downloadSuccess=false; public Download(String url,ViewImage Midlet) { this.url=url; this.Midlet=Midlet; } public void run() { // TODO Auto-generated method stub try{ getImage(url); }catch(Exception e){ } } private void getImage(String url) throws IOException { ContentConnection connection=(ContentConnection)Connector.open(url); DataInputStream iStrm=connection.openDataInputStream(); ByteArrayOutputStream bStrm=null; Image im=null; try{ byte[] imageData; int length=(int)connection.getLength(); if(length!=-1) { imageData=new byte[length]; iStrm.readFully(imageData); } else { bStrm=new ByteArrayOutputStream(); int ch; while((ch=iStrm.read())!=-1) { bStrm.write(ch); } imageData=bStrm.toByteArray(); } im=Image.createImage(imageData, 0, imageData.length); } finally{ if(connection!=null) connection.close(); if(iStrm!=null) iStrm.close(); if(bStrm!=null) bStrm.close(); } if(im==null) Midlet.showImage(false); else { Midlet.im=im; Midlet.showImage(true); } } } }
最终显示结果如下图所示:
注:1.ContentConnection connection=(ContentConnection)Connector.open(url);
为什么用ContentConnection 而不用HttpConnection ,个人认为应该可以,没有试验,有时间验证一下。
2.
byte[] imageData; int length=(int)connection.getLength(); if(length!=-1) { imageData=new byte[length]; iStrm.readFully(imageData); } else { bStrm=new ByteArrayOutputStream(); int ch; while((ch=iStrm.read())!=-1) { bStrm.write(ch); } imageData=bStrm.toByteArray(); } im=Image.createImage(imageData, 0, imageData.length);
不是很明白!
2.开发Socket网络连接应用
我做的是一个聊天软件,有服务端和客户端,代码如下:
Server.java
import java.io.*; import javax.microedition.io.*; import javax.microedition.lcdui.*; public class Server implements Runnable,CommandListener { private SocketMidlet parent; private Display dis; private Form f; private StringItem si; private TextField tf; private boolean stop; private Command sendCommand=new Command("发送",Command.OK,1); private Command exitCommand=new Command("退出",Command.EXIT,1); InputStream is; OutputStream os; SocketConnection sc; ServerSocketConnection scn; Sender sender; public Server(SocketMidlet m) { // TODO Auto-generated constructor stub parent=m; dis=Display.getDisplay(parent); f=new Form("Socket服务器端"); si=new StringItem("状态:",""); tf=new TextField("发送:","",30,TextField.ANY); f.append(si); f.append(tf); f.addCommand(exitCommand); f.setCommandListener(this); dis.setCurrent(f); this.start(); } public void start() { Thread t=new Thread(this); t.start(); } public void run() { // TODO Auto-generated method stub try{ si.setText("等待客户端连接"); scn=(ServerSocketConnection)Connector.open("socket://:50009"); sc=(SocketConnection)scn.acceptAndOpen(); si.setText("Connection accepted"); is=sc.openInputStream(); os=sc.openOutputStream(); sender=new Sender(os); f.addCommand(sendCommand); while(true) { StringBuffer sb=new StringBuffer(); int c=0; while(((c=is.read())!='\n')&&(c!=-1)) { sb.append((char)c); } if(c==-1) break; si.setText("接收到的消息:"+ sb.toString()); } stop(); si.setText("连接已经关闭"); f.removeCommand(sendCommand); }catch(IOException ioe){ if(ioe.getMessage().equals("ServerSocket Open")) { Alert a=new Alert("Server","端口可能已经被占用",null,AlertType.ERROR); a.setTimeout(Alert.FOREVER); a.setCommandListener(this); dis.setCurrent(a); } else if(!stop) { ioe.printStackTrace(); } }catch(Exception e) { } } public void stop() { try{ stop=true; if(is!=null) is.close(); if(os!=null) os.close(); if(sc!=null) sc.close(); if(scn!=null) scn.close(); }catch(Exception e){ } } public void commandAction(Command c, Displayable s) { // TODO Auto-generated method stub if(c==sendCommand&&!parent.isPaused()) sender.send(tf.getString()); if((c==Alert.DISMISS_COMMAND)||c==exitCommand) { try{ parent.notifyDestroyed(); parent.destroyApp(true); }catch(Exception e){ } } } }
Cilent.java
import java.io.*; import javax.microedition.io.*; import javax.microedition.lcdui.*; public class Client implements Runnable,CommandListener { private SocketMidlet parent; private Display dis; private Form f; private StringItem si; private TextField tf; private boolean stop; private Command sendCommand=new Command("发送",Command.OK,1); private Command exitCommand=new Command("退出",Command.EXIT,1); InputStream is; OutputStream os; SocketConnection sc; Sender sender; public Client(SocketMidlet m) { // TODO Auto-generated constructor stub parent=m; dis=Display.getDisplay(parent); f=new Form("Socket服务器端"); si=new StringItem("状态:",""); tf=new TextField("发送:","",30,TextField.ANY); f.append(si); f.append(tf); f.addCommand(exitCommand); f.setCommandListener(this); dis.setCurrent(f); this.start(); } public void start() { Thread t=new Thread(this); t.start(); } public void run() { // TODO Auto-generated method stub try{ sc=(SocketConnection)Connector.open("socket://localhost:50009"); si.setText("已经连接到服务器"); is=sc.openInputStream(); os=sc.openOutputStream(); sender=new Sender(os); f.addCommand(sendCommand); while(true) { StringBuffer sb=new StringBuffer(); int c=0; while(((c=is.read())!='\n')&&(c!=-1)) { sb.append((char)c); } if(c==-1) break; si.setText("接收到的消息:"+ sb.toString()); } stop(); si.setText("连接已经关闭"); f.removeCommand(sendCommand); }catch(ConnectionNotFoundException cnfe){ Alert a=new Alert("Client","请先运行服务器节点",null,AlertType.ERROR); a.setTimeout(Alert.FOREVER); a.setCommandListener(this); dis.setCurrent(a); }catch(IOException ioe) { if(!stop) { ioe.printStackTrace(); } }catch(Exception e) { } } public void stop() { try{ stop=true; if(is!=null) is.close(); if(os!=null) os.close(); if(sc!=null) sc.close(); }catch(Exception e){ } } public void commandAction(Command c, Displayable s) { // TODO Auto-generated method stub if(c==sendCommand&&!parent.isPaused()) sender.send(tf.getString()); if((c==Alert.DISMISS_COMMAND)||c==exitCommand) { try{ parent.notifyDestroyed(); parent.destroyApp(true); }catch(Exception e){ } } } }
Sender.java
import java.io.*; public class Sender extends Thread { private OutputStream os; private String message; public Sender(OutputStream os) { // TODO Auto-generated constructor stub this.os=os; start(); } public synchronized void send(String msg) { message=msg; notify(); } public synchronized void run() { while(true) { if(message==null) { try{ wait(); }catch(Exception e){ } } if(message==null) break; try{ os.write(message.getBytes()); os.write("\r\n".getBytes()); }catch(Exception e){ } message=null; } } public synchronized void stop() { message=null; notify(); } }
SocketMidlet.java
import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class SocketMidlet extends MIDlet implements CommandListener{ private static final String SERVER="服务器"; private static final String CLIENT="客户端"; private static final String[] names={SERVER,CLIENT}; private Display dis; private Form f; private ChoiceGroup cg; private boolean isPaused; private Server server; private Client client; private Command startCommand=new Command("启动",Command.OK,1); private Command exitCommand=new Command("退出",Command.EXIT,1); public SocketMidlet() { // TODO Auto-generated constructor stub dis=Display.getDisplay(this); f=new Form("Socket连接示例"); cg=new ChoiceGroup("选择端点类型",Choice.EXCLUSIVE,names,null); f.append(cg); f.addCommand(startCommand); f.addCommand(exitCommand); f.setCommandListener(this); dis.setCurrent(f); } public boolean isPaused() { return isPaused; } protected void destroyApp(boolean arg0) throws MIDletStateChangeException { // TODO Auto-generated method stub if(server!=null) server.stop(); if(client!=null) client.stop(); } protected void pauseApp() { // TODO Auto-generated method stub isPaused=true; } protected void startApp() throws MIDletStateChangeException { // TODO Auto-generated method stub isPaused=false; } public void commandAction(Command c, Displayable s) { // TODO Auto-generated method stub if(c==exitCommand) { try { destroyApp(false); notifyDestroyed(); } catch (MIDletStateChangeException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else if(c==startCommand) { String name=cg.getString(cg.getSelectedIndex()); if(name.equals(SERVER)) { server=new Server(this); } else if(name.equals(CLIENT)) { client=new Client(this); } } } }
运行结果如下:
大体上和开发Socket网络连接应用差不多,只是Socket是面向连接的,而他不是,我也没有认真看,呵呵!