您的位置:首页 > 其它

J2ME蓝牙实战入门

2008-05-01 06:41 423 查看
概述
目前,很多手机已经具备了蓝牙功能。虽然MIDP2.0没有包括蓝牙API,但是JCP定义了JSR82,JavaAPIsforBluetoothWirelessTechnology(JABWT).这是一个可选API,很多支持MIDP2.0的手机已经实现了,比如Nokia6600,Nokia6670,Nokia7610等等。对于一个开发者来说,如果目标平台支持JSR82的话,在制作联网对战类型游戏或者应用的时候,蓝牙是一个相当不错的选择。本文给出了一个最简单的蓝牙应用的J2ME程序,用以帮助开发者快速的掌握JSR82。该程序分别在2台蓝牙设备上安装后,一台设备作为服务端先运行,一台设备作为客户端后运行。在服务端上我们发布了一个服务,该服务的功能是把客户端发过来的字符串转变为大写字符串。客户端起动并搜索到服务端的服务后,我们就可以从客户端的输入框里输入任意的字符串,发送到服务端去,同时观察服务端的反馈结果。
本文并不具体讲述蓝牙的运行机制和JSR82的API结构,关于这些知识点,请参考本文的参考资料一节,这些参考资料会给你一个权威的精确的解释。
实例代码
该程序包括3个java文件。一个是MIDlet,另外2个为服务端GUI和客户端GUI。该程序已经在wtk22模拟器和Nokia6600,Nokia6670两款手机上测试通过。
StupidBTMIDlet.java
importjavax.microedition.lcdui.Alert;
importjavax.microedition.lcdui.AlertType;
importjavax.microedition.lcdui.Command;
importjavax.microedition.lcdui.CommandListener;
importjavax.microedition.lcdui.Display;
importjavax.microedition.lcdui.Displayable;
importjavax.microedition.lcdui.List;
importjavax.microedition.midlet.MIDlet;
importjavax.microedition.midlet.MIDletStateChangeException;
/**
*@authorJagie
*
*MIDlet
*/
publicclassStupidBTMIDletextendsMIDletimpleMEntsCommandListener{
Listlist;
ServerBoxsb;
ClientBoxcb;
/*
*(non-Javadoc)
*
*@seejavax.microedition.midlet.MIDlet#startApp()
*/
protectedvoidstartApp()throwsMIDletStateChangeException{
list=newList("傻瓜蓝牙入门",List.IMPLICIT);
list.append("Client",null);
list.append("Server",null);
list.setCommandListener(this);
Display.getDisplay(this).setCurrent(list);
}
/**
*debug方法
*@params要显示的字串
*/
publicvoidshowString(Strings){
Displayabledp=Display.getDisplay(this).getCurrent();
Alertal=newAlert(null,s,null,AlertType.INFO);
al.setTiMEout(2000);
Display.getDisplay(this).setCurrent(al,dp);
}
/**
*显示主菜单
*
*/
publicvoidshowMainMEnu(){
Display.getDisplay(this).setCurrent(list);
}
protectedvoidpauseApp(){
//TODOAuto-generatedMEthodstub
}
publicvoidcommandAction(Commandcom,Displayabledisp){
if(com==List.SELECT_COMMAND){
Listlist=(List)disp;
intindex=list.getSelectedIndex();
if(index==1){
if(sb==null){
sb=newServerBox(this);
}
sb.setString(null);
Display.getDisplay(this).setCurrent(sb);
}else{
//每次都生成新的客户端实例
cb=null;
System.gc();
cb=newClientBox(this);
Display.getDisplay(this).setCurrent(cb);
}
}
}
protectedvoiddestroyApp(booleanarg0)throwsMIDletStateChangeException{
//TODOAuto-generatedMEthodstub
}
}
ClientBox.java
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.util.Vector;
importjavax.microedition.io.Connector;
importjavax.microedition.io.StreamConnection;
importjavax.microedition.lcdui.Command;
importjavax.microedition.lcdui.CommandListener;
importjavax.microedition.lcdui.Displayable;
importjavax.microedition.lcdui.Form;
importjavax.microedition.lcdui.Gauge;
importjavax.microedition.lcdui.StringItem;
importjavax.microedition.lcdui.TextField;
//jsr082API
importjavax.bluetooth.BluetoothStateException;
importjavax.bluetooth.DeviceClass;
importjavax.bluetooth.DiscoveryAgent;
importjavax.bluetooth.DiscoveryListener;
importjavax.bluetooth.LocalDevice;
importjavax.bluetooth.RemoteDevice;
importjavax.bluetooth.ServiceRecord;
importjavax.bluetooth.UUID;
/**
*客户端GUI
*@authorJagie
*
*TODOTochangethetemplateforthisgeneratedtypecomMEntgoto
*Window-Preferences-Java-CodeStyle-CodeTemplates
*/
publicclassClientBoxextendsFormimpleMEntsRunnable,CommandListener,
DiscoveryListener{
//字串输入框
TextFieldinput=newTextField(null,"",50,TextField.ANY);
//loger
StringItemresult=newStringItem("结果:","");
privateDiscoveryAgentdiscoveryAgent;
privateUUID[]uuidSet;
//响应服务的UUID
privatestaticfinalUUIDECHO_SERVER_UUID=newUUID(
"F0E0D0C0B0A000908070605040302010",false);
//设备集合
Vectordevices=newVector();
//服务集合
Vectorrecords=newVector();
//服务搜索的事务id集合
int[]transIDs;
StupidBTMIDletmidlet;
publicClientBox(StupidBTMIDletmidlet){
super("");
this.midlet=midlet;
this.append(result);
this.addCommand(newCommand("取消",Command.CANCEL,1));
this.setCommandListener(this);
newThread(this).start();
}
publicvoidcommandAction(Commandarg0,Displayablearg1){
if(arg0.getCommandType()==Command.CANCEL){
midlet.showMainMEnu();
}else{
//匿名内部Thread,访问远程服务。
ThreadfetchThread=newThread(){
publicvoidrun(){
for(inti=0;i0){
this.append(input);
this.addCommand(newCommand("发送",Command.OK,0));
}
//删除Gauge
this.delete(1);
}
/**
*debug
*@params
*/
privatevoidshowInfo(Strings){
StringBuffersb=newStringBuffer(result.getText());
if(sb.length()>0){
sb.append("/n");
}
sb.append(s);
result.setText(sb.toString());
}
/**
*回调方法
*/
publicvoiddeviceDiscovered(RemoteDevicebtDevice,DeviceClasscod){
if(devices.indexOf(btDevice)==-1){
devices.addEleMEnt(btDevice);
}
}
/**
*回调方法,唤醒初始化线程
*/
publicvoidinquiryCompleted(intdiscType){
synchronized(this){
notify();
}
}
/**
*回调方法
*/
publicvoidservicesDiscovered(inttransID,ServiceRecord[]servRecord){
for(inti=0;i if(transIDs[i]==transID){
transIDs[i]=-1;
break;
}
}
//如果所有的设备都已经搜索服务完毕,则唤醒初始化线程。
booleanfinished=true;
for(inti=0;i if(transIDs[i]!=-1){
finished=false;
break;
}
}
if(finished){
synchronized(this){
notify();
}
}
}
}
ServerBox.java
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.util.Vector;
importjavax.bluetooth.DiscoveryAgent;
importjavax.bluetooth.LocalDevice;
importjavax.bluetooth.ServiceRecord;
importjavax.bluetooth.UUID;
importjavax.microedition.io.Connector;
importjavax.microedition.io.StreamConnection;
importjavax.microedition.io.StreamConnectionNotifier;
importjavax.microedition.lcdui.Command;
importjavax.microedition.lcdui.CommandListener;
importjavax.microedition.lcdui.Displayable;
importjavax.microedition.lcdui.TextBox;
importjavax.microedition.lcdui.TextField;
/**
*服务端GUI
*@authorJagie
*
*TODOTochangethetemplateforthisgeneratedtypecomMEntgoto
*Window-Preferences-Java-CodeStyle-CodeTemplates
*/
publicclassServerBoxextendsTextBoximpleMEntsRunnable,CommandListener{
Commandcom_pub=newCommand("开启服务",Command.OK,0);
Commandcom_cancel=newCommand("终止服务",Command.CANCEL,0);
Commandcom_back=newCommand("返回",Command.BACK,1);
LocalDevicelocalDevice;
StreamConnectionNotifiernotifier;
ServiceRecordrecord;
booleanisClosed;
ClientProcessorprocessor;
StupidBTMIDletmidlet;
//响应服务的uuid
privatestaticfinalUUIDECHO_SERVER_UUID=newUUID(
"F0E0D0C0B0A000908070605040302010",false);
publicServerBox(StupidBTMIDletmidlet){
super(null,"",500,TextField.ANY);
this.midlet=midlet;
this.addCommand(com_pub);
this.addCommand(com_back);
this.setCommandListener(this);
}
publicvoidrun(){
booleanisBTReady=false;
try{
localDevice=LocalDevice.getLocalDevice();
if(!localDevice.setDiscoverable(DiscoveryAgent.GIAC)){
showInfo("无法设置设备发现模式");
return;
}
//prepareaURLtocreateanotifier
StringBufferurl=newStringBuffer("btspp://");
//indicatethisisaserver
url.append("localhost").append(':');
//addtheUUIDtoidentifythisservice
url.append(ECHO_SERVER_UUID.toString());
//addthenaMEforourservice
url.append(";naME=EchoServer");
//requestalloftheclientnottobeauthorized
//soMEdevicesfailonauthorize=true
url.append(";authorize=false");
//createnotifiernow
notifier=(StreamConnectionNotifier)Connector
.open(url.toString());
record=localDevice.getRecord(notifier);
//reMEmberwe'vereachedthispoint.
isBTReady=true;
}catch(Exceptione){
e.printStackTrace();
}
//nothingtodoifnobluetoothavailable
if(isBTReady){
showInfo("初始化成功,等待连接");
this.removeCommand(com_pub);
this.addCommand(com_cancel);
}else{
showInfo("初始化失败,退出");
return;
}
//生成服务端服务线程对象
processor=newClientProcessor();
//ok,startacceptingconnectionsthen
while(!isClosed){
StreamConnectionconn=null;
try{
conn=notifier.acceptAndOpen();
}catch(IOExceptione){
//wrongclientorinterrupted-continueanyway
continue;
}
processor.addConnection(conn);
}
}
publicvoidpublish(){
isClosed=false;
this.setString(null);
newThread(this).start();
}
publicvoidcancelService(){
isClosed=true;
showInfo("服务终止");
this.removeCommand(com_cancel);
this.addCommand(com_pub);
}
/*
*(non-Javadoc)
*
*@seejavax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command,
*javax.microedition.lcdui.Displayable)
*/
publicvoidcommandAction(Commandarg0,Displayablearg1){
if(arg0==com_pub){
//发布service
publish();
}elseif(arg0==com_cancel){
cancelService();
}else{
cancelService();
midlet.showMainMEnu();
}
}
/**
*内部类,服务端服务线程。
*@authorJagie
*
*TODOTochangethetemplateforthisgeneratedtypecomMEntgoto
*Window-Preferences-Java-CodeStyle-CodeTemplates
*/
privateclassClientProcessorimpleMEntsRunnable{
privateThreadprocessorThread;
privateVectorqueue=newVector();
privatebooleanisOk=true;
ClientProcessor(){
processorThread=newThread(this);
processorThread.start();
}
publicvoidrun(){
while(!isClosed){
synchronized(this){
if(queue.size()==0){
try{
//阻塞,直到有新客户连接
wait();
}catch(InterruptedExceptione){
}
}
}
//处理连接队列
StreamConnectionconn;
synchronized(this){
if(isClosed){
return;
}
conn=(StreamConnection)queue.firstEleMEnt();
queue.removeEleMEntAt(0);
processConnection(conn);
}
}
}
/**
*往连接队列添加新连接,同时唤醒处理线程
*@paramconn
*/
voidaddConnection(StreamConnectionconn){
synchronized(this){
queue.addEleMEnt(conn);
notify();
}
}
}
/**
*从StreamConnection读取输入
*@paramconn
*@return
*/
privateStringreadInputString(StreamConnectionconn){
StringinputString=null;
try{
DataInputStreamdis=conn.openDataInputStream();
inputString=dis.readUTF();
dis.close();
}catch(Exceptione){
e.printStackTrace();
}
returninputString;
}
/**
*debug
*@params
*/
privatevoidshowInfo(Strings){
StringBuffersb=newStringBuffer(this.getString());
if(sb.length()>0){
sb.append("/n");
}
sb.append(s);
this.setString(sb.toString());
}
/**
*处理客户端连接
*@paramconn
*/
privatevoidprocessConnection(StreamConnectionconn){
//读取输入
StringinputString=readInputString(conn);
//生成响应
StringoutputString=inputString.toUpperCase();
//输出响应
sendOutputData(outputString,conn);
try{
conn.close();
}catch(IOExceptione){
}//ignore
showInfo("客户端输入:"+inputString+",已成功响应!");
}
/**
*输出响应
*@paramoutputData
*@paramconn
*/
privatevoidsendOutputData(StringoutputData,StreamConnectionconn){
try{
DataOutputStreamdos=conn.openDataOutputStream();
dos.writeUTF(outputData);
dos.close();
}catch(IOExceptione){
}
}
}
小结
本文给出了一个简单的蓝牙服务的例子。旨在帮助开发者快速掌握JSR82.如果该文能对你有所启发,那就很好了。
参考资料
1.http://developers.sun.com/techtopics/mobility/apis/articles/bluetoothintro/
JSR82API介绍(英文)
2.MEdev.com/article/showarticle.asp?articleid=249" />http://www.j2MEdev.com/Article/ShowArticle.asp?ArticleID=249
JSR82API介绍(中文)
3.http://www.jcp.org/en/jsr/detail?id=82
JSR82Specification.
4.WTK22,BluetoothDemo项目
作者简介
陈万飞,网名Jagie,培训师,爱好java技术.可通过chen_cwf@163
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: