Namespaces

Variants
Actions

Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries over the next few weeks. Thanks for all your past and future contributions.

ServiceRecord.getConnectionURL() returns null instead of connection string. How to retrieve the string value?

From Wiki
Jump to: navigation, search
Article Metadata
Compatibility
Platform(s): S60 3rd Edition
Series 40
Symbian
Article
Created: User:Technical writer 1 (20 Dec 2007)
Last edited: hamishwillee (17 Jun 2013)

Overview

Bluetooth client uses services which can be obtained from the Bluetooth server. Services are defined and made available to clients in form of service records.

In Mobile Java, the ServiceRecord interface describes characteristics of a Bluetooth service. A ServiceRecord contains a set of service attributes, where each service attribute is an (ID, value) pair. A Bluetooth attribute ID is a 16-bit unsigned integer, and an attribute value is a DataElement.

ServiceRecords are made available to a client application via an argument of the servicesDiscovered method of the DiscoveryListener interface. There might be many service attributes in a service record, and the Service Discovery Protocol makes it possible to specify the subset of the service attributes that an SDP client wants to retrieve from a remote service record.


Description

In order to connect to the service, the URL for connecting to the server needs to be acquired. For that purpose, getConnectionURL(int securityValue, boolean masterValue) returns a string including optional parameters that can be used for connecting to the service. The return value can be used as the first argument to Connector.open(). The URL is of the following format:

 btspp://000B1C71DA17:2;authenticate=false;encrypt=false;master=false


The usage of the method is as follows: First the service record will be retrieved from the vector to which all the discovered services have been placed with the servicesDiscovered() method. After that, the URL can be retrieved from the service record. Below is an example of the usage (here 'services' as the vector and 0 as the index value of the service):


  ServiceRecord service = (ServiceRecord) services.elementAt(0);
url[0] = service.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);



However, with some S60 3rd Edition devices, this method may not always work properly, resulting in null instead of the string value. For such cases, there is a workaround based on constructing the connection string by acquiring the required information from the service record.



Solution

First address the service to which you want to connect by choosing the proper service record. The record will be acquired from vector as defined previously:


 ServiceRecord service=(ServiceRecord) services.elementAt(indexValue);

Service record includes a 0protocol descriptor list which defines protocol stacks for gaining access to the service. Each stack is considered as a data element sequence which consists of protocol descriptors. A protocol descriptor is in turn also considered as a data element sequence which consists of the following data elements: UUID (protocol identifier such as L2CAP, RFCOMM, etc.) and protocol-specific parameters, such as version number and connection port number. The service attribute ID of 0x0004 will be used for acquiring the list:




  DataElement descriptorList = service.getAttributeValue(0x0004);

After acquiring the descriptor list, use the getValue() method to get a descriptor list as a DATSEQ (DATa element SEQuence) object. By using enumeration, you can go through the acquired protocol descriptor list which consists of the following data elements: ( "L2CAP" , "RFCOMM, channel number" ). After skipping the first descriptor (L2CAP) and choosing the next one, RFCOMM, and then going through its DATSEQ object (skipping the UUID), the channel identifier number for the RFCOMM is acquired.

  Enumeration enum = (Enumeration) descriptorList.getValue(); //DATSEQ
enum.nextElement(); // Skipping L2CAP
DataElement RFCOMMdescriptor = (DataElement) enum.nextElement();
enum = (Enumeration) RFCOMMdescriptor.getValue(); // DATSEQ
enum.nextElement(); // Skipping UUID (=RFCOMM)
DataElement RFCOMMchannelNum = (DataElement) enum.nextElement(); //channel number

Finally, the server channel identifier number assigned to the service is set: the legal channel range as specified in the JSR-82 Bluetooth API specification is from 1 up to 30 as an unsigned 8-bit integer, and this is assured by handling it within the if-else statement accordingly. After that, the url string will be parsed and can be used to connect the service.




  try {
 
long channelNum;
 
if (DataElement.U_INT_8 == RFCOMMchannelNum.getDataType() ||
DataElement.U_INT_16 == RFCOMMchannelNum.getDataType() ||
DataElement.INT_16 == RFCOMMchannelNum.getDataType() )
{
byte[] allBytes = (byte[]) RFCOMMchannelID.getValue();
channelNum = bytes[0]; // Legal channel range is 1-30,
retrieving first byte
}
else
{
channelID = RFCOMMchannelNum.getLong(); // U_INT_1
}
 
StringBuffer nameBuffer = new StringBuffer(5+3+12+1+2+19+14+13);
nameBuffer.append("btspp");
nameBuffer.append("://");
nameBuffer.append(sr.getHostDevice().getBluetoothAddress());
nameBuffer.append(":");
nameBuffer.append(channel);
nameBuffer.append(";authenticate=false");
nameBuffer.append(";encrypt=false");
nameBuffer.append(";master=false");
String name = nameBuffer.toString();
StreamConnection connection = (StreamConnection)
Connector.open(name);
}
catch(Exception e) {
System.err.println(e);
 
}
This page was last modified on 17 June 2013, at 04:50.
111 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×