龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > JAVA开发 >

J2ME蓝牙实战入门

时间:2009-12-23 15:42来源:未知 作者:admin 点击:
分享到:
目前,很多手机已经具备了蓝牙功能。虽然MIDP2.0没有包括蓝牙API,但是JCP定义了JSR82, Java APIs for Bluetooth Wireless Technology (JABWT).这是一个可选API,很多支持MIDP2.0的手机已经实现了,比如Nok

  目前,很多手机已经具备了蓝牙功能。虽然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.java
  
  
  
  import 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.java
  
  
  
  import 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;i<records.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();
             }
         }
  
     }
  
  }

Photoshop教程 数据结构 五笔输入法专题 QQ病毒专题 共享上网专题 Google工具和服务专题
  

  
  

精彩图集

赞助商链接