📄 netlayer.java
字号:
package btchat;
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;
/**
* BlueChat example application.
* Originally published in Java Developer's Journal (volume 9 issue 2).
* Updated by Ben Hui on www.benhui.net.
* Copyright: (c) 2003-2004
* Author: Ben Hui
*
* YOU ARE ALLOWED TO USE THIS CODE FOR EDUCATIONAL, PERSONAL TRAINNING,
* REFERENCE PURPOSE. YOU MAY DISTRIBUTE THIS CODE AS-IS OR MODIFIED FORM.
* HOWEVER, YOU CANNOT USE THIS CODE FOR COMMERCIAL PURPOSE. THIS INCLUDE,
* BUT NOT LIMITED TO, PRODUCING COMMERCIAL SOFTWARE, CONSULTANT SERVICE,
* PROFESSIONAL TRAINNING MATERIAL.
*
* This is the main class for handling bluetooth connectivity and
* device/service discovery process. This class does many things, including
* - search for bluetooth devices (query())
* - create a local BlueChat server and register it with bluetooth (run())
* - search for remote BlueChat services using searchServices()
* - handle incoming connection request from remote BlueChat
* - establish connection to remote BlueChat
*
* @author Ben Hui
* @version 1.0
*/
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;
// BlueChat specific service UUID
// note: this UUID must be a string of 32 char
// do not use the 0x???? constructor because it won't
// work. not sure if it is a N6600 bug or not
private final static UUID uuid = new UUID("102030405060708090A0B0C0D0E0F010", false);
//
// major service class as SERVICE_TELEPHONY
private final static int SERVICE_TELEPHONY = 0x400000;
// reference to local bluetooth device singleton
LocalDevice localDevice = null;
// reference to local discovery agent singleton
DiscoveryAgent agent = null;
// local BlueChat service server object
StreamConnectionNotifier server;
// reference to BListener implementation. for BlueChat event callback
BTListener callback = null;
boolean done = false;
String localName = "";
// list of active EndPoints. all messages will be sent to all
// active EndPoints
Vector endPoints = new Vector();
// list of pending EndPoints. this is used to keep track of
// discovered devices waiting for service discovery. When all the near-by
// BlueChat service has been discovered, this list will be cleared until the
// next inquiry
Vector pendingEndPoints = new Vector();
// map ServiceRecord to EndPoint
// see DoServiceDiscovery and serviceSearchCompleted
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)
{
log( "invoke init()" );
try {
this.localName = name;
this.callback = callback;
//
// initialize the JABWT stack
localDevice = LocalDevice.getLocalDevice(); // obtain reference to singleton
localDevice.setDiscoverable(DiscoveryAgent.GIAC); // set Discover mode to GIAC
agent = localDevice.getDiscoveryAgent(); // obtain reference to singleton
// print local device information
Util.printLocalDevice( localDevice );
// start bluetooth server socket
// see run() for implementation of local BlueChat service
Thread thread = new Thread( this );
thread.start();
}
catch (BluetoothStateException e) {
e.printStackTrace();
log(e.getClass().getName()+" "+e.getMessage());
}
catch (IOException e) {
e.printStackTrace();
log(e.getClass().getName()+" "+e.getMessage());
}
}
public void disconnect()
{
log("invoke disconnect()");
// stop server socket, not longer accept client connection
done = true;
try {
// this close will interrupt server.acceptAndOpen()
// wake it up to exit
server.close();
}
catch (IOException ex) {
}
// stop each EndPoint reader and sender threads
// and send TERMINATE signal to other connected
// BlueChat peers
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 {
log("invoke query()");
// although JSR-82 provides the ability to lookup
// cached and preknown devices, we intentionally by-pass
// them and go to discovery mode directly.
// this allow us to retrieve the latest active BlueChat parties
agent.startInquiry(DiscoveryAgent.GIAC, new Listener());
}
catch (BluetoothStateException e)
{
e.printStackTrace();
log(e.getClass().getName()+" "+e.getMessage());
}
}
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; // not found, return null
}
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; // not found, return null
}
/**
* Send a string message to all active EndPoints
* @param s
*/
public void sendString( String s )
{
log("invoke sendString string="+s);
for ( int i=0; i < endPoints.size(); i++ )
{
EndPoint endpt = (EndPoint) endPoints.elementAt( i );
// put the string on EndPoint, so sender will send the message
endpt.putString( NetLayer.SIGNAL_MESSAGE, s );
}
}
/**
* Clean up the resource for a EndPoint, remove it from the active list.
* This is triggered by a remote EndPoint leaving the network
* @param endpt
*/
// remove this end point from the active end point list
endPoints.removeElement( endpt );
}
/**
* Implement local BlueChat service.
*/
public void run()
{
// connection to remote device
StreamConnection c = null;
try
{
// Create a server connection object, 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 ) );
// Print the service record, which already contains
// some default values
Util.printServiceRecord( rec );
// Set the Major Service Classes flag in Bluetooth stack.
// We choose Object Transfer Service
rec.setDeviceServiceClasses(
SERVICE_TELEPHONY );
} catch (Exception e)
{
e.printStackTrace();
log(e.getClass().getName()+" "+e.getMessage());
}
while( !done)
{
try {
///////////////////////////////
log("local service waiting for client connection");
// this message is to inform user that the server is up and ready
ChatMain.instance.gui_log( "", "Ready to accept connection. Wait..." );
//
// start accepting client connection.
// This method will block until a client
// connected
c = server.acceptAndOpen();
log("local service accept a new client connection");
//
// 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 )
{
// this is a safe guard to assure that this client
// has not been connected before
log("client connection end point already exist.. ignore this connection");
} else
{
// - create a new EndPoint object
// - initialize the member variables
// - start the data reader and sender threads.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -