最佳的线程联网类
以前自己打开Http连接,从未开启过线程,我自己对线程用的也不是很熟悉,今天去论坛求救,立马得到结果,结果来自亚日的一篇文章J2ME http连接的例子,他的代码写的很清晰,代码结构也不错,是用lcdui的高级UI写的。
但我用的是LWUIT的包,很多写法和lcdui不一样,我就对着它的代码研究了一下,自己写了一个LWUIT的版本,非常感谢亚日提供的这个例子。
首先看看亚日的例子,代码注释写的很清楚,看懂还是比较容易的。
代码
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
/**
* HttpDemo 增加网址输入以及取消功能
*
* @author kf156(亚日)
*
*/
public class HttpTest extends MIDlet implements CommandListener {
public static final byte WAIT = 0;// 等待
public static final byte CONNECT = 1;// 连接中
public static final byte SUCCESS = 2;// 成功
public static final byte FAIL = 3;// 失败
int state;// 当前状态
Display display = Display.getDisplay(this);
Form form = new Form("HttpTest");
// StringBuffer sb = new StringBuffer("");
// StringItem si = new StringItem(null, sb.toString());
Command connect = new Command("联网", Command.OK, 1);
Command cls = new Command("清除网址", Command.OK, 1);
Command cancel = new Command("取消", Command.CANCEL, 1);
Command exit = new Command("退出", Command.EXIT, 1);
Command back = new Command("返回", Command.BACK, 1);
ChoiceGroup cmwapCG;// 接入方式
TextField urlTF;// 网址输入框
String url;// 网址
Http http;// 网络线程
Form page;// 页面
Alert waitPage;// 等待界面
public HttpTest() {
state = WAIT;// 等待状态
// 初始化等待界面
waitPage = new Alert("请等待", "网络连接中...", null, AlertType.INFO);
waitPage.addCommand(cancel);
waitPage.setCommandListener(this);
waitPage.setTimeout(Alert.FOREVER);
// 初始化页面
page = new Form("访问的页面");
page.addCommand(back);
page.setCommandListener(this);
// 初始化
cmwapCG = new ChoiceGroup("网络接入方式:", Choice.MULTIPLE,
new String[] { "CMWAP" }, null);
urlTF = new TextField("请输入网址:",
"http://avatar.csdn.net/5/F/0/2_kf156.jpg", 100, TextField.URL);
form.append(cmwapCG);
form.append(urlTF);
// form.append(si);
form.addCommand(connect);
form.addCommand(cls);
// form.addCommand(cancel);
form.addCommand(exit);
form.setCommandListener(this);
}
protected void destroyApp(boolean b) {
}
protected void pauseApp() {
}
protected void startApp() {
display.setCurrent(form);
}
public void commandAction(Command c, Displayable d) {
if (c == connect) {// 联网
if (checkError())
return;
// display.setCurrent(waitPage);
http = new Http();
new Thread(http).start();
} else if (c == cancel) {// 取消
http.cancel();
http = null;
display.setCurrent(form);
} else if (c == back) {// 返回
page.deleteAll();
display.setCurrent(form);
} else if (c == cls) {// 清除数据
// cls();
urlTF.setString("");
} else if (c == exit) {// 退出
destroyApp(true);
notifyDestroyed();
}
}
// private void cls() {
// form.deleteAll();// 删除日志
// sb.delete(0, sb.length());
// si.setText(null);
// form.append(cmwapCG);
// form.append(urlTF);
// form.append(si);
// }
/**
* 判断是否正确
*
* @return
*/
private boolean checkError() {
url = urlTF.getString();
if (state == CONNECT) {
addStr("当前已有网络连接,请稍候");
return true;
} else if (url == null || url.trim().equals("")) {
addStr("url不能为空");
return true;
}
if (!url.toLowerCase().startsWith("http://")) {// 添加http://
url = "http://" + url;
}
System.out.println(url);
return false;
}
/**
* 添加文字
*
* @param str
* 要添加的文字
*/
private void addStr(String str) {
// sb.append(str + "\n");
// si.setText(sb.toString());
System.out.println(str);
}
/**
* 获取URL域名
*
* @param srcUrl
* @param domain
* true为截域名,false为截地址
* @return
*/
private String getURLhost(String srcUrl) {
int k = srcUrl.toLowerCase().indexOf("/", 7);
if (k == -1)
return srcUrl.substring(7);
return srcUrl.substring(7, k);
}
/**
*
* 字符串替换方法(字符串替换字符串)
*
* @author kf156
*
* @param text
* 文本
* @param oldStr
* 旧字符串
* @param newStr
* 新字符串
* @return
*/
public static String replace(String text, String oldStr, String newStr) {
int oldLen = oldStr.length();
int k = 0;
while (k + oldLen <= text.length()) {// 检测到字符串末尾
k = text.indexOf(oldStr, k);// 从k处查找oldStr,并返回位置
if (k == -1)// 若查不到,则跳出
return text;
// 若有,则将其替换为newStr
text = text.substring(0, k) + newStr
+ text.substring(k += oldLen, text.length());
}
return text;
}
class Http implements Runnable {
HttpConnection http;
boolean cancel;// 是否取消
public void cancel() {
cancel = true;
state = WAIT;// 等待状态
}
public void run() {
// cls();
state = CONNECT;
addStr("网络连接中...");
InputStream is = null;
try {
boolean cmwap = cmwapCG.isSelected(0);// 是否走CMWAP
String host = getURLhost(url);
System.out.println(host);
String _url = cmwap ? replace(url, host, "10.0.0.172:80") : url;
http = (HttpConnection) Connector.open(_url, Connector.READ,
true);
if (cmwap)
http.setRequestProperty("X-Online-Host", host);
http.setRequestMethod(HttpConnection.GET);
cmwapCG.setSelectedIndex(0, true);
String contentType = http.getHeaderField("Content-Type");
// System.out.println(contentType);
addStr("Content-Type=" + contentType);
if (cancel) {// 中途结束
addStr("已取消");
return;
}
if (contentType != null
&& contentType.indexOf("text/vnd.wap.wml") != -1) {// 过滤移动资费页面
addStr("移动资费页面,过滤!");
http.close();
http = null;
http = (HttpConnection) Connector.open(_url,
Connector.READ, true);
if (cmwap)
http.setRequestProperty("X-Online-Host", host);
http.setRequestMethod(HttpConnection.GET);
contentType = http.getHeaderField("Content-Type");
addStr("Content-Type=" + contentType);
}
int code = http.getResponseCode();
addStr("HTTP Code :" + code);
if (code == 200) {// 成功
addStr("网络联网成功,接收数据...");
is = http.openInputStream();
byte[] b = new byte[1024];
int len = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
while ((len = is.read(b)) != -1) {
if (cancel) {// 中途结束
addStr("已取消");
return;
}
dos.write(b, 0, len);
}
byte[] data = baos.toByteArray();
if (contentType != null
&& contentType.toLowerCase().indexOf("image") != -1) {// 图片
try {
Image image = Image.createImage(data, 0,
data.length);
addStr("数据接收完毕,显示图片");
// form.append(image);
page.append(image);
} catch (Exception e) {
addStr("生成图片失败 " + e.toString());
page.append("生成图片失败 " + e.toString());
}
} else { // 文字
addStr("数据接收完毕,显示内容");
String s = null;
if (contentType != null
&& contentType.toLowerCase().indexOf("utf-8") != -1)
s = new String(data, "UTF-8");
else
s = new String(data);
// form.append(s);
page.append(s);
}
data = null;
dos.close();
dos = null;
baos.close();
baos = null;
is.close();
is = null;
state = SUCCESS;
} else {
addStr("访问页面失败");
page.append("访问页面失败: " + code);
state = FAIL;
}
} catch (IOException e) {
addStr("联网发生异常:" + e.toString());
e.printStackTrace();
if (!cancel)
page.append("网络异常:" + e.toString());
state = FAIL;
} catch (Exception e) {
addStr("发生异常:" + e.toString());
e.printStackTrace();
if (!cancel)
page.append("异常:" + e.toString());
state = FAIL;
} finally {
if (is != null) {// 关闭is
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
is = null;
}
if (http != null) {// 关闭http
try {
http.close();
} catch (IOException e) {
e.printStackTrace();
}
http = null;
}
}
if (!cancel)
display.setCurrent(page);// 显示页面
}
}
}
下面的代码是我用LWUIT改造的代码,代码可以自己修改一下,让代码结构更良好,可以把Http类抽出来。
代码
import com.sun.lwuit.CheckBox;
import com.sun.lwuit.Command;
import com.sun.lwuit.Display;
import com.sun.lwuit.Form;
import com.sun.lwuit.Image;
import com.sun.lwuit.Label;
import com.sun.lwuit.TextField;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.midlet.*;
/**
* @author 水货程序员
* Demo作为学习交流使用
*/
public class HttpTest extends MIDlet implements ActionListener {
public static final byte WAIT = 0;//等待
public static final byte CONNECT = 1;//连接中
public static final byte SUCCESS = 2;//成功
public static final byte FAIL = 3;//失败
int state;
Command connect = new Command("联网", 1);
Command cls = new Command("清除网址", 2);
Command cancel = new Command("取消", 3);
Command exit = new Command("退出", 4);
Command back = new Command("返回", 5);
CheckBox cmwapCG;//接入方式
TextField urlTF;//网址输入框
String url;//网址
Http http;//网络线程
Form page;//页面
Form waitPage;//等待界面
public void actionPerformed(ActionEvent evt) {
int cmdId = evt.getCommand().getId();
switch (cmdId) {
case 1://连接
if (checkError()) {
return;
}
http = new Http();
new Thread(http).start();
break;
case 2://清除网址
urlTF.setText("");
break;
case 3://取消
http.cancel();
http = null;
showTestForm();
break;
case 4://退出
destroyApp(true);
notifyDestroyed();
break;
case 5://返回
showTestForm();
break;
}
}
/**
* 在LWUIT的主类里面,Form不能声明为属性,否则会出现NullPointerException。
* 取得图片后,再返回时,重新new一下cmwapCB,urlTF,否则会报
* Component is already contained in Container的异常。
*/
public void showTestForm() {
Form form = new Form("HttpTest");
cmwapCG = new CheckBox("CMWAP");
urlTF = new TextField("http://avatar.csdn.net/5/F/0/2_kf156.jpg");
form.addComponent(cmwapCG);
form.addComponent(urlTF);
form.addCommand(connect);
form.addCommand(cls);
form.addCommand(exit);
form.addCommandListener(this);
form.show();
}
public void startApp() {
Display.init(this);
state = WAIT;//等待
//waitPage = new Form()
page = new Form("访问的页面");
page.addCommand(back);
page.addCommandListener(this);
cmwapCG = new CheckBox("CMWAP");
urlTF = new TextField("http://avatar.csdn.net/5/F/0/2_kf156.jpg");
url = urlTF.getText();
showTestForm();
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
/**
* 检验URL正确性
* @return
*/
private boolean checkError() {
url = urlTF.getText();
if (state == CONNECT) {
System.out.println("当前已有网络连接,请稍后");
return true;
} else if (url == null || url.trim().equals("")) {
return true;
}
if (!url.toLowerCase().startsWith("http://")) {
// 添加http://
url = "http://" + http;
}
System.out.println(url);
return false;
}
/**
* 获取URL域名
* 例如http://www.google.cn,域名为www.google.cn
* http://blog.csdn.net/pjw100,域名为blog.csdn.net,会把/pjw100截掉。
* @param srcUrl
* @return
*/
private String getURLhost(String srcUrl) {
int k = srcUrl.toLowerCase().indexOf("/", 7);
if (k == -1) {
return srcUrl.substring(7);
}
return srcUrl.substring(7, k);
}
public static String replace(String text, String oldStr, String newStr) {
int oldLen = oldStr.length();
int k = 0;
while (k + oldLen < text.length()) {//检测到字符串末尾
k = text.indexOf(oldStr, k);//查找字符串
if (k == -1) {//若查不到,跳出
return text;
}
//有则替换
text = text.substring(0, k) + newStr + text.substring(k += oldLen, text.length());
}
return text;
}
class Http implements Runnable {
HttpConnection http;
boolean cancel;//是否取消
public void cancel() {
cancel = true;
state = WAIT;//等待状态
}
public void run() {
state = CONNECT;
System.out.println("网络连接中...");
InputStream is = null;
try {
boolean cmwap = cmwapCG.isSelected();
String host = getURLhost(url);
System.out.println(host);
String _url = cmwap ? replace(url, host, "10.0.0.172:80") : url;
http = (HttpConnection) Connector.open(_url, Connector.READ, true);
if (cmwap) {
http.setRequestProperty("X-Online-Host", host);
}
http.setRequestMethod(HttpConnection.GET);
String contentType = http.getHeaderField("Content-Type");
if (cancel) {//中途取消
return;
}
if (contentType != null && contentType.indexOf("text/vnd.wap.wml") != -1) {
//过滤移动资费
http.close();
http = null;
http = (HttpConnection) Connector.open(_url, Connector.READ, true);
if (cmwap) {
http.setRequestProperty("X-Online-Host", host);
}
http.setRequestMethod(HttpConnection.GET);
contentType = http.getHeaderField("Content-Type");
}
int code = http.getResponseCode();
if (code == 200) {//联网成功
is = http.openInputStream();
byte[] b = new byte[1024];
int len = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
while ((len = is.read(b)) != -1) {
if (cancel) {
//取消
return;
}
dos.write(b, 0, len);
}
byte[] data = baos.toByteArray();
if (contentType != null && contentType.toLowerCase().indexOf("image") != -1) {
try {
Image image = Image.createImage(data, 0, data.length);
System.out.println("数据接收完毕,显示图片");
Label l = new Label(image);
page.addComponent(l);
} catch (Exception ex) {
System.out.println("生成图片失败" + ex.toString());
Label err = new Label("生成图片失败" + ex.toString());
page.addComponent(err);
}
} else {//文字
System.out.println("数据接收完毕,显示内容");
String s = null;
if (contentType != null && contentType.toLowerCase().indexOf("utf-8") != -1) {
s = new String(data, "UTF-8");
} else {
s = new String(data);
}
page.addComponent(new Label(s));
}
data = null;
dos.close();
dos = null;
baos.close();
baos = null;
is.close();
is = null;
state = SUCCESS;
} else {
page.addComponent(new Label("访问页面失败:" + code));
state = FAIL;
}
} catch (IOException ex) {
System.out.println("联网发生异常:" + ex.toString());
ex.printStackTrace();
if (!cancel) {
page.addComponent(new Label("网络异常:" + ex.toString()));
}
state = FAIL;
} catch (Exception ex) {
System.out.println("发生异常" + ex.toString());
ex.printStackTrace();
if (!cancel) {
page.addComponent(new Label("异常:" + ex.toString()));
}
state = FAIL;
} finally {
if (is != null) {//关闭is
try {
is.close();
} catch (IOException ex) {
ex.printStackTrace();
}
is = null;
}
if (http != null) {//关闭http
try {
http.close();
} catch (IOException ex) {
ex.printStackTrace();
}
http = null;
}
}
if (!cancel) {
page.show();
}
}
}
}