import javax.bluetooth.*;
import java.util.Vector;
public class BluetoothServiceFinder implements DiscoveryListener {
public static String getConnectionURL(String uuid) throws BluetoothStateException {
BluetoothServiceFinder finder
= new BluetoothServiceFinder(BluetoothReceiver.UUID);
return finder.getFirstURL();
}
private DiscoveryAgent agent;
private int serviceSearchCount;
private ServiceRecord record;
// I'd rather use ArrayList, but Vector is more
// commonly available in J2ME environments
private Vector devices = new Vector();
private String uuid;
// Every search has an ID that allows it to be cancelled.
// We need to store these so we can tell when all searches
// are complete.
private int[] transactions;
private BluetoothServiceFinder(String serviceUUID)
throws BluetoothStateException {
this.uuid = serviceUUID;
agent = LocalDevice.getLocalDevice().getDiscoveryAgent();
int maxSimultaneousSearches = Integer.parseInt(
LocalDevice.getProperty("bluetooth.sd.trans.max"));
transactions = new int[maxSimultaneousSearches];
// We need to initialize the transactions list with illegal
// values. According to spec, the transaction ID is supposed to be
// positive, and thus non-zero. However, several implementations
// get this wrong and use zero as a transaction ID.
for (int i = 0; i < maxSimultaneousSearches; i++) {
transactions[i] = -1;
}
}
private void addTransaction(int transactionID) {
for (int i = 0; i < transactions.length; i++) {
if (transactions[i] == -1) {
transactions[i] = transactionID;
return;
}
}
}
private void removeTransaction(int transactionID) {
for (int i = 0; i < transactions.length; i++) {
if (transactions[i] == transactionID) {
transactions[i] = -1;
return;
}
}
}
private boolean searchServices(RemoteDevice[] devices) {
UUID[] searchList = { new UUID(uuid, false) };
for (int i = 0; i < devices.length; i++) {
if (record != null) {
return true;
}
try {
// don't care about attributes
int transactionID = agent.searchServices(null, searchList, devices[i], this);
addTransaction(transactionID);
}
catch (BluetoothStateException ex) {
}
synchronized (this) {
serviceSearchCount++;
if (serviceSearchCount == transactions.length) {
try {
this.wait();
}
catch (InterruptedException ex) {
// continue
}
}
}
}
while (serviceSearchCount > 0) { // unfinished searches
synchronized (this) {
try {
this.wait();
}
catch (InterruptedException ex) {
// continue
}
}
}
if (record != null) return true;
else return false;
}
private String getFirstURL() {
try {
agent.startInquiry(DiscoveryAgent.GIAC, this);
synchronized (this) {
try {
this.wait();
}
catch (InterruptedException ex) {
}
}
}
catch (BluetoothStateException ex) {
System.out.println("No devices in range");
}
if (devices.size() > 0) {
RemoteDevice[] remotes = new RemoteDevice[devices.size()];
devices.copyInto(remotes);
if (searchServices(remotes)) {
return record.getConnectionURL(
ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
}
}
return null;
}
// DiscoveryListener methods
public void deviceDiscovered(RemoteDevice device, DeviceClass type) {
devices.addElement(device);
}
public void serviceSearchCompleted(int transactionID, int responseCode) {
removeTransaction(transactionID);
serviceSearchCount--;
synchronized (this) {
this.notifyAll();
}
}
public void servicesDiscovered(int transactionID, ServiceRecord[] records) {
if (record == null) {
record = records[0];
for (int i = 0; i < transactions.length; i++) {
if (transactions[i] != -1) {
agent.cancelServiceSearch(transactions[i]);
}
}
}
}
public void inquiryCompleted(int discType) {
synchronized (this) {
this.notifyAll();
}
}
}
|