⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netlayer.java

📁 我自己写的蓝牙例子
💻 JAVA
字号:
import javax.microedition.io.*;
import javax.bluetooth.*;
import java.io.*;
import java.util.*;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.ServiceRecord;

/** 该类的功能是:
* 搜索设备  
* 创建一个服务器,然后进行注册
* 搜索远程设备的服务
* 处理远程服务的连接要求
* 建立远程服务的连接
*/ 

public class NetLayer implements Runnable
{
  public final static int SIGNAL_HANDSHAKE = 0;
  public final static int SIGNAL_MESSAGE = 1;
  public final static int SIGNAL_TERMINATE = 3;
  public final static int SIGNAL_HANDSHAKE_ACK = 4;
  public final static int SIGNAL_TERMINATE_ACK = 5;
  
  
  private final static UUID uuid = new UUID("102030405060708090A0B0C0D0E0F010", false);
    
    private final static int SERVICE_TELEPHONY = 0x400000;
    
  //本地蓝牙设备
  LocalDevice localDevice = null;
  // 本地的发现代理
  DiscoveryAgent agent = null;
  
  //本地的服务
  StreamConnectionNotifier server;
  
  //回调接口
  BTListener callback = null;

  //停止标志量
  boolean done = false;

  //本机用户名
  String localName = "";

  //活动终结点的列表
  Vector endPoints = new Vector();

  // 未决的结点,还没发现服务的结点
  Vector pendingEndPoints = new Vector();

  // map ServiceRecord to EndPoint
  Hashtable serviceRecordToEndPoint = new Hashtable();

  // synchronization lock
  // see DoServiceDiscovery and serviceSearchCompleted
  Object lock = new Object();

  // timer to schedule task to do service discovery
  // see inquiryCompleted
  Timer timer = new Timer();
  
    public NetLayer()
  {
  }
  
   public void init(String name, BTListener callback)
  {
    try {
      this.localName = name;
      this.callback = callback;

      // initialize the JABWT stack
      localDevice = LocalDevice.getLocalDevice(); 
      localDevice.setDiscoverable(DiscoveryAgent.GIAC); 
      agent = localDevice.getDiscoveryAgent(); 
      // 打开蓝牙服务器socket接口
      Thread thread = new Thread( this );
      thread.start();
    }
    catch (BluetoothStateException e) {
      e.printStackTrace();

    }
    catch (IOException e) {
      e.printStackTrace();
    }
  }
  
   public void disconnect()
  {
    //断开接口,不再响应连接请求
    done = true;
    try {
      // 打断server.acceptAndOpen()使之停止
      server.close();
    }
    catch (IOException ex) {
    }

    // 停止终结点的发送和读取线程
    // 并发送结束信号给其他连接
    
    for ( int i=0; i < endPoints.size(); i++ )
    {
      EndPoint endpt = (EndPoint) endPoints.elementAt( i );
      endpt.putString( NetLayer.SIGNAL_TERMINATE, "end" );
      endpt.sender.stop();
      endpt.reader.stop();

    }
  }
  
    public void query()
  {
    try {
      // 这里只检取最新的设备,而不查询已有的
      agent.startInquiry(DiscoveryAgent.GIAC, new Listener());
    }
    catch (BluetoothStateException e)
    {
      e.printStackTrace();
    }
  }
  
  //通过设备查询终结点
   public EndPoint findEndPointByRemoteDevice( RemoteDevice rdev )
  {
    for ( int i=0; i < endPoints.size(); i++ )
    {
      EndPoint endpt = (EndPoint) endPoints.elementAt( i );
      if ( endpt.remoteDev.equals( rdev ) )
      {
        return endpt;
      }
    }
    return null; 
  }

  //通过id查询终结点
  public EndPoint findEndPointByTransId( int id )
  {
    for ( int i=0; i < pendingEndPoints.size(); i++ )
    {
      EndPoint endpt = (EndPoint) pendingEndPoints.elementAt( i );
      if ( endpt.transId == id )
      {
        return endpt;
      }
    }
    return null; 
  }


  /**
   * 发送消息给所有活动接点
   * @param s
   */
  public void sendString( String s )
  {
    for ( int i=0; i < endPoints.size(); i++ )
    {
      EndPoint endpt = (EndPoint) endPoints.elementAt( i );
      endpt.putString( NetLayer.SIGNAL_MESSAGE, s );
    }
  }

  /**
   * 删除接点
   *  该方法由远程设备从网络中删除时触发该方法(This is triggered by a remote EndPoint leaving the network)
   * @param endpt
   */
  public void cleanupRemoteEndPoint( EndPoint endpt )
  {
    endpt.reader.stop();
    endpt.sender.stop();
    
    // 从活动终结点列表中移除该接点
    endPoints.removeElement( endpt );
  }
  
    public void run()
  {
    //连接到远程设备
    StreamConnection c = null;
    try
    {
      // 创建一个服务连接, using a
      // Serial Port Profile URL syntax and our specific UUID
      // and set the service name to BlueChatApp
      
      server =  (StreamConnectionNotifier)Connector.open(
          "btspp://localhost:" + uuid.toString() +";name=BlueChatApp");

      // Retrieve the service record template
      ServiceRecord rec = localDevice.getRecord( server );

      // set ServiceRecrod ServiceAvailability (0x0008) attribute to indicate our service is available
      // 0xFF indicate fully available status
      // This operation is optional
      rec.setAttributeValue( 0x0008, new DataElement( DataElement.U_INT_1, 0xFF ) );


      // Set the Major Service Classes flag in Bluetooth stack.
      // We choose Object Transfer Service
      rec.setDeviceServiceClasses(
          SERVICE_TELEPHONY  );



    } catch (Exception e)
    {
      e.printStackTrace();
    }

    while( !done)
    {
      try {
        c = server.acceptAndOpen();

        // retrieve the remote device object
        RemoteDevice rdev = RemoteDevice.getRemoteDevice( c );
        //
        // check to see if the EndPoint already exist
        EndPoint endpt = findEndPointByRemoteDevice( rdev );
        if ( endpt != null )
        {
          // 为了确保以前没有该客户端如果有则忽略该连接
        } else
        {
          //否则新建一个接点并且打开发送接受线程
          endpt = new EndPoint( this, rdev, c);

          Thread t1 = new Thread( endpt.sender );
          t1.start();

          Thread t2 = new Thread( endpt.reader );
          t2.start();

          // 添加该结点
          endPoints.addElement( endpt );
        }


      }
      catch (IOException e) {
        e.printStackTrace();

        // 如果有任何异常, 则推断连接失败
        // failed and close it. closing the connection will cause
        // the reader and sender thread to exit (because they will got
        // exception as well).
        if (c != null)
          try {
            c.close();
          }
          catch (IOException e2) {
          }

      }
      finally {
      }
    }
  } 
  
   class Listener implements DiscoveryListener
  {

    /**
     * 当一个设备被发现时,把它放入未决的终结点列表中
     * 当所有的设备搜索完后将进行服务搜索
     * A service search will happen when all the qualifying devices are discovered.
     *
     * @param remoteDevice
     * @param deviceClass
     */
     
    public void deviceDiscovered(RemoteDevice remoteDevice,
                                 DeviceClass deviceClass)
    {
     
        try
        {
          EndPoint endpt = new EndPoint(NetLayer.this, remoteDevice, null);
          pendingEndPoints.addElement( endpt );

        } catch (Exception e)
        {
          e.printStackTrace();
        }
    }
    
     public void inquiryCompleted(int transId)
    {

      // wait 100ms and start doing service discovery
      // the choice of 100ms is really just a guess
      timer.schedule( new DoServiceDiscovery(), 100 );
    }

    /**
     * a service is discovered from a remote device.
     * when a BlueChat service is discovered, we establish a connection to
     * this service. This signal joining the existing virtual chat room.
     * @param transId
     * @param svcRec
     */
    public void servicesDiscovered(int transId, ServiceRecord[] svcRec)
    {

      try {

        for ( int i=0; i< svcRec.length; i++ )
        {
          EndPoint endpt = findEndPointByTransId( transId );

          serviceRecordToEndPoint.put( svcRec[i], endpt );
        }

      }
      catch (Exception e) {
        e.printStackTrace();
      }
    }

    /**
     * service discovery is completed.
     * @param int0
     * @param int1
     */
    public void serviceSearchCompleted(int transID, int respCode)
    {
    	
      for ( Enumeration records = serviceRecordToEndPoint.keys(); records.hasMoreElements(); )
      {
        try {


        ServiceRecord rec = (ServiceRecord) records.nextElement();

        // We make an assumption that the first service is BlueChat. In fact, only one
        // service record will be found on each device.
        // Note: we know the found service is BlueChat service because we search on specific UUID,
        // this UUID is unique to us.
        String url  = rec.getConnectionURL( ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false );
        StreamConnection con = (StreamConnection)Connector.open( url );

        // retrieve the pending EndPoint and initialize the necessary member variables
        // to activate the EndPoint. this includes
        // - initialize connection
        // - start sender and reader thread
        EndPoint endpt = (EndPoint) serviceRecordToEndPoint.get( rec );
        if ( endpt != null )
        {
          endpt.con = con;


          Thread t1 = new Thread( endpt.sender );
          t1.start();

          Thread t2 = new Thread( endpt.reader );
          t2.start();

          endPoints.addElement( endpt );
          

          // once a EndPoint established, the BlueChat client is responsible to initiate the
          // handshake protocol.
          endpt.putString( NetLayer.SIGNAL_HANDSHAKE, localName );


        } else
        {

        }

        } catch (Exception e)
        {
          e.printStackTrace();

        }
      } // for

      // finished process current batch of service record
      // clear it and service discovery on next device
      serviceRecordToEndPoint.clear();

      synchronized( lock )
      {
        // unlock to proceed to service search on next device
        // see DoServiceDiscovery.run()
        lock.notifyAll();
      }

    }

  } // inner class Listener
  
  class DoServiceDiscovery extends TimerTask
  {
    public void run()
    {
      //对每个结点搜索服务
      for (int i = 0; i < pendingEndPoints.size(); i++)
      {

        EndPoint endpt = (EndPoint) pendingEndPoints.elementAt(i);

        try {

          //
          // searchServices return a transaction id, which we will used to
          // identify which remote device the service is found in our callback
          // listener (class Listener)
          //<div></div>
          // note: in theory, only one runtine instance of Listener is needed
          // to handle all discovery callback. however, there is a bug in rococo
          // simualtor that cause callback fails with one instance of used
          // so we make a new Listener for every searchServices()
          endpt.transId = agent.searchServices(null // null to indicate retrieve default attributes
                                               ,
                                               new UUID[] { uuid }  // BlueChat service UUID SerialPort
                                               ,
                                               endpt.remoteDev,
                                               new Listener());

          // wait until the above service discovery is completed
          // because N6600 cannot handle more than one service discovery
          // request at the same time
          // see serviceSearchCompleted()
          synchronized( lock )
          {
            try {
              lock.wait();
            }
            catch (InterruptedException ex) {
            }
          }
        }
        catch (BluetoothStateException e) {
          e.printStackTrace();
        }

      } // for

      // 所有服务都发现时,将删除列表中所有的结点
      pendingEndPoints.removeAllElements();
    }

  }

  
  
  
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -