J2ME蓝牙程序开发实战入门

2016-02-19 19:32 52 1 收藏

有了下面这个J2ME蓝牙程序开发实战入门教程,不懂J2ME蓝牙程序开发实战入门的也能装懂了,赶紧get起来装逼一下吧!

【 tulaoshi.com - 编程语言 】

  概述 目前,很多手机已经具备了蓝牙功能。虽然MIDP2.0没有包括蓝牙API,但是JCP定义了JSR82, Java APIs for Bluetooth Wireless Technology (JABWT).这是一个可选API,很多支持MIDP2.0的手机已经实现了,比如Nokia 6600, Nokia 6670,Nokia7610等等。对于一个开发者来说,假如目标平台支持JSR82的话,在制作联网对战类型游戏或者应用的时候,蓝牙是一个相当不错的选择。本文给出了一个最简单的蓝牙应用的J2ME程序,用以帮助开发者快速的把握JSR82。该程序分别在2台蓝牙设备上安装后,一台设备作为服务端先运行,一台设备作为客户端后运行。在服务端上我们发布了一个服务,该服务的功能是把客户端发过来的字符串转变为大写字符串。客户端起动并搜索到服务端的服务后,我们就可以从客户端的输入框里输入任意的字符串,发送到服务端去,同时观察服务端的反馈结果。
  
      本文并不具体讲述蓝牙的运行机制和JSR82的API结构,关于这些知识点,请参考本文的参考资料一节,这些参考资料会给你一个权威的精确的解释。
  
    实例代码
  该程序包括3个java文件。一个是MIDlet,另外2个为服务端GUI和客户端GUI。该程序已经在wtk22模拟器和Nokia 6600,Nokia 6670两款手机上测试通过。
  
    StupidBTMIDlet.javaimport javax.microedition.lcdui.Alert; import javax.microedition.lcdui.AlertType; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.List; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; /**  * @author Jagie  *   *  MIDlet  */ public class StupidBTMIDlet extends MIDlet implements CommandListener {     List list;     ServerBox sb;     ClientBox cb;     /*      * (non-Javadoc)      *       * @see javax.microedition.midlet.MIDlet#startApp()      */     protected void startApp() throws MIDletStateChangeException {         list = new List("傻瓜蓝牙入门", List.IMPLICIT);
           list.append("Client", null);         list.append("Server", null);         list.setCommandListener(this);         Display.getDisplay(this).setCurrent(list);     }          /**      * debug方法      * @param s 要显示的字串      */     public void showString(String s) {         Displayable dp = Display.getDisplay(this).getCurrent();         Alert al = new Alert(null, s, null, AlertType.INFO);         al.setTimeout(2000);         Display.getDisplay(this).setCurrent(al, dp);     }          /**      * 显示主菜单      *      */     public void showMainMenu() {         Display.getDisplay(this).setCurrent(list);     }          protected void pauseApp() {         // TODO Auto-generated method stub     }     public void commandAction(Command com, Displayable disp) {         if (com == List.SELECT_COMMAND) {             List list = (List) disp;             int index = list.getSelectedIndex();             if (index == 1) {                 if (sb == null) {                     sb = new ServerBox(this);
                   }                 sb.setString(null);                 Display.getDisplay(this).setCurrent(sb);             } else {                 //每次都生成新的客户端实例                 cb = null;                 System.gc();                 cb = new ClientBox(this);                 Display.getDisplay(this).setCurrent(cb);             }         }     }     protected void destroyApp(boolean arg0) throws MIDletStateChangeException {         // TODO Auto-generated method stub     } }   ClientBox.javaimport java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Vector; import javax.microedition.io.Connector; import javax.microedition.io.StreamConnection; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Form; import javax.microedition.lcdui.Gauge; import javax.microedition.lcdui.StringItem; import javax.microedition.lcdui.TextField; //jsr082 API import javax.bluetooth.BluetoothStateException; import javax.bluetooth.DeviceClass; import javax.bluetooth.DiscoveryAgent; import javax.bluetooth.DiscoveryListener; import javax.bluetooth.LocalDevice; import javax.bluetooth.RemoteDevice; import javax.bluetooth.ServiceRecord;
   import javax.bluetooth.UUID; /**  * 客户端GUI  * @author Jagie  *  * TODO To change the template for this generated type comment go to  * Window - Preferences - Java - Code Style - Code Templates  */ public class ClientBox extends Form implements Runnable, CommandListener,         DiscoveryListener {          //字串输入框     TextField input = new TextField(null, "", 50, TextField.ANY);     //loger     StringItem result = new StringItem("结果:", "");     private DiscoveryAgent discoveryAgent;          private UUID[] uuidSet;     //响应服务的UUID     private static final UUID ECHO_SERVER_UUID = new UUID(             "F0E0D0C0B0A000908070605040302010", false);     //设备集合     Vector devices = new Vector();     //服务集合     Vector records = new Vector();          //服务搜索的事务id集合     int[] transIDs;     StupidBTMIDlet midlet;     public ClientBox(StupidBTMIDlet midlet) {         super("");         this.midlet=midlet;                  this.append(result);                  this.addCommand(new Command("取消",Command.CANCEL,1));         this.setCommandListener(this);                  new Thread(this).start();     }
            public void commandAction(Command arg0, Displayable arg1) {         if(arg0.getCommandType()==Command.CANCEL){             midlet.showMainMenu();         }else{             //匿名内部Thread,访问远程服务。             Thread fetchThread=new Thread(){                 public void run(){                     for(int i=0;irecords.size();i++){                         ServiceRecord sr=(ServiceRecord)records.elementAt(i);                         if(AccessService(sr)){                             //访问到一个可用的服务即可                             break;                         }                     }                 }             };             fetchThread.start();         }              }               private boolean  accessService(ServiceRecord sr){         boolean result=false;          try {             String url = sr.getConnectionURL(
                       ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);             StreamConnection    conn = (StreamConnection) Connector.open(url);                          DataOutputStream dos=conn.openDataOutputStream();             dos.writeUTF(input.getString());             dos.close();             DataInputStream dis=conn.openDataInputStream();             String echo=dis.readUTF();             dis.close();             showInfo("反馈结果是:"+echo);             result=true;                      } catch (IOException e) {                      }         return result;     }     public synchronized void run() {         //发现设备和服务的过程中,给用户以Gauge         Gauge g=new Gauge(null,false,Gauge.INDEFINITE,Gauge.CONTINUOUS_RUNNING);         this.append(g);         showInfo("蓝牙初始化...");         boolean isBTReady = false;         try {             LocalDevice localDevice = LocalDevice.getLocalDevice();             discoveryAgent = localDevice.getDiscoveryAgent();             isBTReady = true;         } catch (Exception e) {
               e.printStackTrace();         }         if (!isBTReady) {             showInfo("蓝牙不可用");             //删除Gauge             this.delete(1);             return;         }         uuidSet = new UUID[2];         //标志我们的响应服务的UUID集合         uuidSet[0] = new UUID(0x1101);         uuidSet[1] = ECHO_SERVER_UUID;                  try {             discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);         } catch (BluetoothStateException e) {         }         try {             //阻塞,由inquiryCompleted()回调方法唤醒             wait();         } catch (InterruptedException e1) {                          e1.printStackTrace();         }         showInfo("设备搜索完毕,共找到"+devices.size()+"个设备,开始搜索服务");         transIDs = new int[devices.size()];         for (int i = 0; i  devices.size(); i++) {             RemoteDevice rd = (RemoteDevice) devices.elementAt(i);             try {                 //记录每一次服务搜索的事务id                 transIDs[i] = discoveryAgent.searchServices(null, uuidSet,
                           rd, this);             } catch (BluetoothStateException e) {                 continue;             }         }                  try {             //阻塞,由serviceSearchCompleted()回调方法在所有设备都搜索完的情况下唤醒             wait();         } catch (InterruptedException e1) {             e1.printStackTrace();         }                  showInfo("服务搜索完毕,共找到"+records.size()+"个服务,预备发送请求");         if(records.size()0){             this.append(input);             this.addCommand(new Command("发送",Command.OK,0));         }                  //删除Gauge         this.delete(1);              }          /**      * debug      * @param s      */          private void showInfo(String s){         StringBuffer sb=new StringBuffer(result.getText());         if(sb.length()0){             sb.append("");         }         sb.append(s);         result.setText(sb.toString());     }
            /**      * 回调方法      */     public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {         if (devices.indexOf(btDevice) == -1) {             devices.addElement(btDevice);         }     }     /**      * 回调方法,唤醒初始化线程      */     public void inquiryCompleted(int discType) {         synchronized (this) {             notify();         }     }     /**      * 回调方法      */     public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {         for (int i = 0; i  servRecord.length; i++) {             records.addElement(servRecord[i]);         }     }          /**      * 回调方法,唤醒初始化线程      */     public void serviceSearchCompleted(int transID, int respCode) {                  for (int i = 0; i  transIDs.length; i++) {             if (transIDs[i] == transID) {                 transIDs[i] = -1;                 break;             }         }                  //假如所有的设备都已经搜索服务完毕,则唤醒初始化线程。
           boolean finished = true;         for (int i = 0; i  transIDs.length; i++) {             if (transIDs[i] != -1) {                 finished = false;                 break;             }         }         if (finished) {             synchronized (this) {                 notify();             }         }     } }   ServerBox.javaimport java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Vector; import javax.bluetooth.DiscoveryAgent; import javax.bluetooth.LocalDevice; import javax.bluetooth.ServiceRecord; import javax.bluetooth.UUID; import javax.microedition.io.Connector; import javax.microedition.io.StreamConnection; import javax.microedition.io.StreamConnectionNotifier; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.TextBox; import javax.microedition.lcdui.TextField; /**  * 服务端GUI  * @author Jagie  *  * TODO To change the template for this generated type comment go to  * Window - Preferences - Java - Code Style - Code Templates  */ public class ServerBox extends TextBox implements Runnable, CommandListener {     Command com_pub = new Command("开启服务", Command.OK, 0);
       Command com_cancel = new Command("终止服务", Command.CANCEL, 0);     Command com_back = new Command("返回", Command.BACK, 1);     LocalDevice localDevice;     StreamConnectionNotifier notifier;     ServiceRecord record;     boolean isClosed;     ClientProcessor processor;     StupidBTMIDlet midlet;     //响应服务的uuid     private static final UUID ECHO_SERVER_UUID = new UUID(             "F0E0D0C0B0A000908070605040302010", false);     public ServerBox(StupidBTMIDlet midlet) {         super(null, "", 500, TextField.ANY);         this.midlet = midlet;         this.addCommand(com_pub);         this.addCommand(com_back);         this.setCommandListener(this);     }     public void run() {         boolean isBTReady = false;         try {             localDevice = LocalDevice.getLocalDevice();             if (!localDevice.setDiscoverable(DiscoveryAgent.GIAC)) {                 showInfo("无法设置设备发现模式");                 return;             }             // prepare a URL to create a notifier             StringBuffer url = new StringBuffer("btspp://");             // indicate this is a server
               url.append("localhost").append(':');             // add the UUID to identify this service             url.append(ECHO_SERVER_UUID.toString());             // add the name for our service             url.append(";name=Echo Server");             // request all of the client not to be authorized             // some devices fail on authorize=true             url.append(";authorize=false");             // create notifier now             notifier = (StreamConnectionNotifier) Connector                     .open(url.toString());             record = localDevice.getRecord(notifier);             // remember we've reached this point.             isBTReady = true;         } catch (Exception e) {             e.printStackTrace();                      }         // nothing to do if no bluetooth available         if (isBTReady) {             showInfo("初始化成功,等待连接");             this.removeCommand(com_pub);             this.addCommand(com_cancel);         } 
   else {

来源:http://www.tulaoshi.com/n/20160219/1621251.html

延伸阅读
绪论 这篇文章将介绍可升级2D矢量图形API(Scalable 2D Vector Graphics API),它是J2ME的一个可选包。这些API非常易于使用,它们可以用来渲染和转换体积小和伸缩性好的二维(2D)图形,这个可选包在Java社区进程(JCP)中以JSR-226开发。我将会给出API的总括,并且突出典型的用户案例,使用代码演示这些案例。 慨述 ...
一、J2ME中需要的Java基础知识 现在有大部分人,都是从零开始学J2ME的,学习J2ME的时候,总是从Java基础开始学习,而且现在讲Java基础的书籍中都是以J2SE来讲基础,这就给学习造成了一些不必要的麻烦,下面将J2ME中用到的和不需要的Java基础知识做一个简单的说明: J2ME中使用到的Java基础知识: 1、Java语法基础:包括基本数...
J2ME(Java 2 Micro Edition)的出现把Java开发者彻底地引入了开发无线设备应用程序的广阔天地。当然,移动设备因其功能和处理能力而多种多样,但是,J2ME通过定义configurations和profiles而对这些差异性进行了逻辑抽象,然后整合两种设置为在特定移动设备上开发应用程序提供了一套完整的平台和API。 连接限制设备配置CLDC(Con...
一.代码优化 内存会溢出肯定和代码逃不了关系,99.99%学java的人都知道垃圾回收器是java的一大优点并据此来嘲笑C++。显然这个特性为代码编写者省了不少事,但这个特性却带来了不少隐患。举个例子在游戏当中经常有不同场景的切换,如从游戏逻辑退到主菜单逻辑,对游戏逻辑对象的态度很多人会选择忘记等待垃圾回收器来收尸。乍看之下似乎...
一、序言 昨天在网上闲逛,发现一篇讲解用Delphi实现华容道游戏的文章,颇受启发.于是,产生了将华容道游戏移植到手机中去的冲动.现在手机游戏琳琅满目,不一而足,华容道的实现版本也很多.正巧不久前笔者对J2ME下了一番功夫,正想借这个机会小试牛刀。选用J2ME的原因还有一个就是目前Java开发大行其到,无线增殖业务迅猛发...

经验教程

343

收藏

67
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部