📄 bluetoothdiscovery.java
字号:
* respCode:代表了服务搜索如何结束的信息量
*/
public void serviceSearchCompleted( int transID, int respCode )
{
synchronized( block_ss )
{
// 重置服务搜索号
serviceSearchTransId = -1;
if( currServRec != null )
{
// 在foundSericeRecords向量中增加一个元素:currServRec
foundServiceRecords.addElement( currServRec );
urlStrings.addElement( currServRec.getConnectionURL( ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false ) );
//System.out.println("urlString:"+currServRec.getConnectionURL( ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false ));
}
switch( searchType )
{
case SEARCH_CONNECT_FIRST_FOUND:
// 因是只发现一个,所以可以返回了
if( currServRec != null )
{
synchronized( block_m )
{
block_m.notifyAll();
}
return;
}
break;
case SEARCH_CONNECT_ALL_FOUND:
break;
case SEARCH_ALL_DEVICES_SELECT_ONE:
case SEARCH_ALL_DEVICES_SELECT_SEVERAL:
if( currServRec != null )
{
// 更新显示搜索到设备的列表
displayFoundServices();
}
break;
}
// 如果是意外中断的
if( respCode == SERVICE_SEARCH_TERMINATED )
{
synchronized( block_ss )
{
block_ss.notifyAll();
}
}
else
{
// 搜索下一设备
nextDeviceServiceSearch();
}
}
}
/**
* 显示搜索到相关服务的设备
*/
private void displayFoundServices()
{
if( deviceList == null )
{
// 如deviceList为空,则创建一个
int lt;
if( searchType == SEARCH_ALL_DEVICES_SELECT_SEVERAL )
{
lt = List.MULTIPLE;
}
else
{
lt = List.IMPLICIT;
}
deviceList = new DeviceList( lt );
}
// 增加新的服务/设备项
// 得到远端设备的名称
DataElement de = ((ServiceRecord)foundServiceRecords.lastElement()).getAttributeValue( SERVICE_NAME_BASE_LANGUAGE );
System.out.println("de.getDataType()= " + de.getDataType());
String rname = (String) de.getValue();
deviceList.append( rname, null );
}
}//end listener
/**
* 内部类waitOnServSearchTermination
* 当服务搜索被中止时就需要用到该类了,
*
*/
private class waitOnServSearchTermination
extends Thread
{
/**
* Terminates service search.
* Waits until serviceSearchCompleted is called and then
* notifies the searchServices method.
*/
public void run()
{
synchronized( block_ss )
{
if( serviceSearchTransId != -1 )
{ // only if there is a service search active
// 如果正在进行服务搜索,
// 则调用DiscoveryAgent的cancelServiceSearch()方法取消该服务搜索
// serviceSearchTransId为服务搜索号(transID)
discoveryAgent.cancelServiceSearch( serviceSearchTransId );
// wait until service search has terminated
// 等待,直到服务搜索中止
try
{
block_ss.wait();
}
catch(InterruptedException e)
{ }
// 唤醒block_m阻塞的线程,返回到searchService()方法继续运行
synchronized( block_m )
{
block_m.notifyAll();
}
}
}
}
}
/**
* DeviceList : 一个列表类,来显示发现的服务/设备表
*/
private class DeviceList extends List implements CommandListener
{
private Command ok;
private Command stop;
private Command cancel;
/**
* list_type:定义List的选择类型, MULTIPLE(多选)或IMPLICIT(唯一)
*/
public DeviceList( int list_type )
{
super( "Select:", list_type );
ok = new Command( "OK", Command.OK, 1 );
stop = new Command( "Stop", Command.STOP, 1 );
cancel = new Command( "Cancel", Command.CANCEL, 1 );
addCommand( ok );
addCommand( stop );
setCommandListener( this );
display.setCurrent( this );
}
/**
* 取消当前的服务搜索
*/
private void cancelServSearch()
{
synchronized( block_ss )
{
if( serviceSearchTransId != -1 )
{ // only if there is a service search active
// 如果正在进行服务搜索,
// 则调用DiscoveryAgent的cancelServiceSearch()方法取消该服务搜索
// serviceSearchTransId为服务搜索号(transID)
discoveryAgent.cancelServiceSearch( serviceSearchTransId );
// wait until service search has terminated
// 等待,直到服务搜索中止
try
{
block_ss.wait();
}
catch( InterruptedException e )
{ }
}
}
}
/**
* 当没有服务/设备元素需要加入时,则调用ready()方法,
* "Stop"按钮变为"Cancal"按钮
*/
public void ready()
{
removeCommand( stop );
addCommand( cancel );
}
public void commandAction( Command c, Displayable s )
{
int com = c.getCommandType();
if( (c == SELECT_COMMAND) && (searchType == SEARCH_ALL_DEVICES_SELECT_ONE) )
{
// 行为和按了OK按键相同
com = Command.OK;
}
switch( com )
{
case Command.OK:
// 玩家按下了OK按钮,
// 首先取消当前服务搜索
cancelServSearch();
// 删除所有没有选择的服务/设备元素
for( int i=size()-1; i>=0; i-- )
{
if( ! isSelected(i) )
{
urlStrings.removeElementAt(i);
}
}
// 返回到searchService()方法,
// 这时urlStrings向量在已经存在建立连接的url值字符串
synchronized( block_m )
{
block_m.notifyAll();
}
break;
case Command.STOP:
// 玩家按下了STOP按钮
// 首先取消当前服务搜索
cancelServSearch();
ready();
break;
case Command.CANCEL:
// 玩家按下了CANCEL按钮
// 删除urlStrings中的所有元素
urlStrings.removeAllElements();
//
// 返回到主程序中
synchronized( block_m )
{
block_m.notifyAll();
}
break;
}
}
}
/** acceptAndOpenThread.
* 把等待Master端的连接定义为一个线程是为了使玩家可以进行取消操作
* 和IE浏览器的工作机制一样
* 在waitOnConnection()方法中为BluetoothDiscovery加入一个Cancel类型的命令按钮
* 如果查一下MIDP2.0规范,会看到静态值Cancel的定义:
* CANCEL
* public static final int CANCELA command that is a standard negative answer
* to a dialog implemented by current screen.
* Nothing is cancelled automatically by the implementation;
* cancellation is implemented by the commandAction
* provided by the application.
* With this command type,
* the application hints to the implementation
* that the user wants to dismiss the current screen
* without taking any action on anything that has been entered into
* the current screen, and usually that the user wants to
* return to the prior screen.
* In many cases CANCEL is interchangeable with BACK,
* but BACK is mainly used for navigation as in
* a browser-oriented applications.
* Value 3 is assigned to CANCEL.
*
*/
private class acceptAndOpenThread
extends Thread
{
/**
* 等待连接或抛出异常
*/
public void run()
{
StreamConnection con;
// 声明一个长度为一的BluetoothConnection对象数组,
btConnections = new BluetoothConnection[1];
// 广播服务,等待Master端的连接
try
{
con = (StreamConnection) notifier.acceptAndOpen();
btConnections[0] = new BluetoothConnection(con, localName, "Host");
// 读取代表远端设备的名称,在远端设备上是localName,在本地设备就成为了remoteName
String remoteName = btConnections[0].readString();
btConnections[0].setRemoteName( remoteName );
}
catch(Exception e)
{
btConnections[0] = null;
}
closeNotifier();
// 重新唤醒被block_s对象阻塞的线程
// 在waitOnConnection方法中被阻塞了,
// 所以,继续运行waitOnConnection中的代码
synchronized( block_s )
{
block_s.notifyAll();
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -