Namespaces
Variants
Actions

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

Jump to: navigation, search
SignpostIcon Asha Connectivity.png
Article Metadata

Compatibility
Platform(s): S60 3rd Edition

Article
Created: User:Technical writer 1 (20 Dec 2007)
Last edited: hamishwillee (14 Jun 2012)

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 14 June 2012, at 07:09.
111 page views in the last 30 days.
Nokia Developer aims to help you create apps and publish them so you can connect with users around the world.

京ICP备05048969号  © Copyright Nokia 2013 All rights reserved