选择显示字体大小

j2me编程实践之联网开发(1)

由于无线设备所能支持的网络协议非常有限,仅限于http,socket,udp等几种协议,不同的厂家可能还支持其他网络协议,但是,midp 1.0规范规定,http协议是必须实现的协议,而其他协议的实现都是可选的。 因此,为了能在不同类型的手机上移植,我们尽量采用http作为网络连接的首选协议,这样还能重用服务器端的代码。但是,由于http是一个基于文本的效率较低的协议,因此,必须仔细考虑手机和服务器端的通信内容,尽可能地提高效率。

对于midp应用程序,应当尽量做到:

1.发送请求时,附加一个user-agent头,传入midp和自身版本号,以便服务器能识别此请求来自midp应用程序,并且根据版本号发送相应的相应。

2.连接服务器时,显示一个下载进度条使用户能看到下载进度,并能随时中断连接。

3.由于无线网络连接速度还很慢,因此有必要将某些数据缓存起来,可以存储在内存中,也可以放到rms中。

对于服务器端而言,其输出响应应当尽量做到:

1. 明确设置content-length字段,以便midp应用程序能读取http头并判断自身是否有能力处理此长度的数据,如果不能,可以直接关闭连接而不必继续读取http正文。

2. 服务器不应当发送html内容,因为midp应用程序很难解析htmlxml虽然能够解析,但是耗费cpu和内存资源,因此,应当发送紧凑的二进制内容,用dataoutputstream直接写入并设置content-type为application/octet-stream。

3. 尽量不要重定向url,这样会导致midp应用程序再次连接服务器,增加了用户的等待时间和网络流量。

4. 如果发生异常,例如请求的资源未找到,或者身份验证失败,通常,服务器会向浏览器发送一个显示出错的页面,可能还包括一个用户登录的form,但是,向midp发送错误页面毫无意义,应当直接发送一个404或401错误,这样midp应用程序就可以直接读取http头的响应码获取错误信息而不必继续读取相应内容。

5. 由于服务器的计算能力远远超过手机客户端,因此,针对不同客户端版本发送不同响应的任务应该在服务器端完成。例如,根据客户端传送的user-agent头确定客户端版本。这样,低版本的客户端不必升级也能继续使用。

midp的联网框架定义了多种协议的网络连接,但是每个厂商都必须实现http连接,在midp 2.0中还增加了必须实现的https连接。因此,要保证midp应用程序能在不同厂商的手机平台上移植,最好只使用http连接。虽然http是一个基于文本的效率较低的协议,但是由于使用特别广泛,大多数服务器应用的前端都是基于http的web页面,因此能最大限度地复用服务器端的代码。只要控制好缓存,仍然有不错的速度。

sun的midp库提供了javax.microediton.io包,能非常容易地实现http连接。但是要注意,由于网络有很大的延时,必须把联网操作放入一个单独的线程中,以避免主线程阻塞导致用户界面停止响应。事实上,midp运行环境根本就不允许在主线程中操作网络连接。因此,我们必须实现一个灵活的http联网模块,能让用户非常直观地看到当前上传和下载的进度,并且能够随时取消连接。

一个完整的http连接为:用户通过某个命令发起连接请求,然后系统给出一个等待屏幕提示正在连接,当连接正常结束后,前进到下一个屏幕并处理下载的数据。如果连接过程出现异常,将给用户提示并返回到前一个屏幕。用户在等待过程中能够随时取消并返回前一个屏幕。

我们设计一个httpthread线程类负责在后台连接服务器,httplistener接口实现observer(观察者)模式,以便httpthread能提示观察者下载开始、下载结束、更新进度条等。httplistener接口如下:

public interface httplistener {

void onsetsize(int size);

void onfinish(byte[] data, int size);

void onprogress(int percent);

void onerror(int code, string message);

}

实现httplistener接口的是继承自form的一个httpwaitui屏幕,它显示一个进度条和一些提示信息,并允许用户随时中断连接:

public class httpwaitui extends form implements commandlistener,

httplistener {

private gauge gauge;

private command cancel;

private httpthread downloader;

private displayable displayable;

public httpwaitui(string url, displayable displayable) {

super("connecting");

this.gauge = new gauge("progress", false, 100, 0);

this.cancel = new command("cancel", command.cancel, 0);

append(gauge);

addcommand(cancel);

setcommandlistener(this);

downloader = new httpthread(url, this);

downloader.start();

}

public void commandaction(command c, displayable d) {

if(c==cancel) {

downloader.cancel();

controllermidlet.goback();

}

}

public void onfinish(byte[] buffer, int size) { … }

public void onerror(int code, string message) { … }

public void onprogress(int percent) { … }

public void onsetsize(int size) { … }

}

httpthread是负责处理http连接的线程类,它接受一个url和httplistener:

class httpthread extends thread {

private static final int max_length = 20 * 1024; // 20k

private boolean cancel = false;

private string url;

private byte[] buffer = null;

private httplistener listener;

public httpthread(string url, httplistener listener) {

this.url = url;

this.listener = listener;

}

public void cancel() { cancel = true; }

使用get获取内容

我们先讨论最简单的get请求。get请求只需向服务器发送一个url,然后取得服务器响应即可。在httpthread的run()方法中实现如下:

public void run() {

httpconnection hc = null;

inputstream input = null;

try {

hc = (httpconnection)connector.open(url);

hc.setrequestmethod(httpconnection.get); // 默认即为get

hc.setrequestproperty("user-agent", user_agent);

// get response code:

int code = hc.getresponsecode();

if(code!=httpconnection.http_ok) {

listener.onerror(code, hc.getresponsemessage());

return;

}

// get size:

int size = (int)hc.getlength();

// 返回响应大小,或者-1如果大小无法确定

listener.onsetsize(size);

// 开始读响应:

input = hc.openinputstream();

int percent = 0; // percentage

int tmp_percent = 0;

int index = 0; // buffer index

int reads; // each byte

if(size!=(-1))

buffer = new byte[size]; // 响应大小已知,确定缓冲区大小

else

buffer = new byte[max_length];

// 响应大小未知,设定一个固定大小的缓冲区

while(!cancel) {

int len = buffer.length - index;

len = len>128 ? 128 : len;

reads = input.read(buffer, index, len);

if(reads<=0)

break;

index += reads;

if(size>0) { // 更新进度

tmp_percent = index * 100 / size;

if(tmp_percent!=percent) {

percent = tmp_percent;

listener.onprogress(percent);

}

}

}

if(!cancel && input.available()>0) // 缓冲区已满,无法继续读取

listener.onerror(601, "buffer overflow.");

if(!cancel) {

if(size!=(-1) && index!=size)

listener.onerror(102, "content-length does not match.");

else

listener.onfinish(buffer, index);

}

}

catch(ioexception ioe) {

listener.onerror(101, "ioexception: " + ioe.getmessage());

}

finally { // 清理资源

if(input!=null)

try { input.close(); } catch(ioexception ioe) {}

if(hc!=null)

try { hc.close(); } catch(ioexception ioe) {}

}

}

当下载完毕后,httpwaitui就获得了来自服务器的数据,要传递给下一个屏幕处理,httpwaitui必须包含对此屏幕的引用并通过一个setdata(datainputstream input)方法让下一个屏幕能非常方便地读取数据。因此,定义一个datahandler接口:

public interface datahandler {

void setdata(datainputstream input) throws ioexception;

}

httpwaitui响应httpthread的onfinish事件并调用下一个屏幕的setdata方法将数据传递给它并显示下一个屏幕:

public void onfinish(byte[] buffer, int size) {

byte[] data = buffer;

if(size!=buffer.length) {

data = new byte[size];

system.arraycopy(data, 0, buffer, 0, size);

}

datainputstream input = null;

try {

input = new datainputstream(new bytearrayinputstream(data));

if(displayable instanceof datahandler)

((datahandler)displayable).setdata(input);

else

system.err.println("[warning]

displayable object cannot handle data.");

controllermidlet.replace(displayable);

}

catch(ioexception ioe) { … }

}


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons