ServiceRecord Class

Holds an SDP service record.

Definition

Namespace: InTheHand.Net.Bluetooth.Sdp
Assembly: InTheHand.Net.Bluetooth (in InTheHand.Net.Bluetooth.dll) Version: 4.0.32+5cdf1cfd21064ea31c5de33d160200ca1c4bc218
C#
public sealed class ServiceRecord : IEnumerable<ServiceAttribute>, 
	IEnumerable
Inheritance
Object    ServiceRecord
Implements
IEnumerableServiceAttribute, IEnumerable

Remarks

A Service Record is the top-level container in the Service Discovery protocol/database. It contains a list of Service Attributes each identified by a numerical identifier (its ServiceAttributeId), and with its data held in a ServiceElement. ServiceElement has methods to access the various types of data it contains.

The content of the record for a particular service class is defined in the profile’s specification along with the IDs it uses. The IDs for the common standard services have beed defined here, as e.g. ObexAttributeId, BasicPrintingProfileAttributeId, etc. The Service Discovery profile itself defines IDs, some that can be used in any record UniversalAttributeId, and others ServiceDiscoveryServerAttributeId, and BrowseGroupDescriptorAttributeId.

Note that except for the attributes in the “Universal” category the IDs are not unique, for instance the ID is 0x0200 for both VersionNumberList and GroupId from ServiceDiscoveryServerAttributeId and BrowseGroupDescriptorAttributeId respectively.

ServiceRecord provides the normal collection-type methods properties e.g. Count, Contains(ServiceAttributeId), GetAttributeById(ServiceAttributeId), Item and GetEnumerator. So, to access a particular attribute’s content get the ServiceAttribute using one of those methods and then read the data from the ServiceElement. See the example below.

 

The SDP specification defines the content of TextString element type very loosely and they are thus very difficult to handle when reading from a record. The encoding of the string content is not set in the specification, and thus implementors are free to use any encoding they fancy, for instance ASCII, UTF-8, UTF-16, Windows-1252, etc — all of which have been seen in record from real devices. It would have been much more sensible to mandate UTF-8 as the other part of the Bluetooth protocol suite do e.g. the PIN is always stored as a UTF-8 encoded string.

Not only that but some of the attributes defined in the SDP specification can be included in more than one ‘natural language’ version, and the definition of the language and the string’s encoding is not included in the element, but is instead defined in a separate element and the ID of the string attribute modified. Yikes!

This makes it near impossible to decode the bytes in a string element at parse time and create the string object then. Therefore the parser creates an element containing the raw bytes from the string which hopefully the user will know how to decode, passing the required encoding information to one of methods on the element i.e. GetValueAsString(LanguageBaseItem), which takes a multi-language-base item from the same record (see e.g. GetPrimaryLanguageBaseItem), GetValueAsString(Encoding) which takes a .NET Encoding object, or GetValueAsStringUtf8, or GetMultiLanguageStringAttributeById(ServiceAttributeId, LanguageBaseItem) on the record which again takes a multi-language-base item.

 

A Service Record can be created from the source byte array by using the CreateServiceRecordFromBytes(Byte) method or the Parse(Byte, Int32, Int32) on ServiceRecordParser. A record can also be created from a list of ServiceAttribute passed to the constructor #ctor(IListServiceAttribute).

 

From the SDP specification:

  • 2.2 ServiceRecord – “… a list of service attributes.”
  • 2.3 ServiceAttribute – “… two components: an attribute id and an attribute value.”
  • 2.4 Attribute ID – “… a 16-bit unsigned integer”, “…represented as a data element.”
  • 2.5 Attribute Value – “… a variable length field whose meaning is determined by the attribute ID…”, “…represented by a data element.”
  • 3.1 Data Element – “… a typed data representation. It consists of two fields: a header field and a data field. The header field, in turn, is composed of two parts: a type descriptor and a size descriptor. ”
  • 3.2 Data Element Type Descriptor – “… a 5-bit type descriptor.”
  • 3.3 Data Element Size Descriptor – “… The data element size descriptor is represented as a 3-bit size index followed by 0, 8, 16, or 32 bits.”

Example

C#
ServiceRecord record = ...
ServiceAttribute attr = record.GetAttributeById(UniversalAttributeId.ServiceRecordHandle);
ServiceElement element = attr.Value;
if(element.ElementType != ElementType.UInt32) {
  throw new FooException("Invalid record content for ServiceRecordHandle");
}
UInt32 handle = (UInt32)element.Value;
or
VB
Dim bppRecord As ServiceRecord = ...
Dim attr As ServiceAttribute = bppRecord.GetAttributeById(BasicPrintingProfileAttributeId.PrinterName)
Dim element As ServiceElement = attr.Value;
' Spec say it is in UTF-8
Dim printerName As String = element.GetValueAsStringUtf8()

Constructors

ServiceRecord Initializes a new instance of the ServiceRecord class containing no ServiceAttributes.
ServiceRecord(IListServiceAttribute) Initializes a new instance of the ServiceRecord class with the specified set of ServiceAttributes.
ServiceRecord(ServiceAttribute) Initializes a new instance of the ServiceRecord class with the specified set of ServiceAttributes.

Properties

AttributeIds Get a list of the numerical IDs of the Attributes in the record as an IListT of ServiceAttributeId.
Count Gets the count of attributes in the record.
Item Gets the attribute at the specified index.
SourceBytes Get the raw byte array from which the record was parsed.

Methods

Contains(ServiceAttributeId) Determines whether a service attribute with the specified ID is in the List.
Contains(ServiceAttributeId, LanguageBaseItem) Determines whether a TextString service attribute with the specified ID and natural language is in the List.
CreateLanguageBasedAttributeId Create the attribute id resulting for adding the language base attribute id.
CreateServiceRecordFromBytes Create a ServiceRecord by parsing the given array of Byte.
Equals
(Inherited from Object)
GetAttributeById(ServiceAttributeId) Returns the attribute with the given ID.
GetAttributeById(ServiceAttributeId, LanguageBaseItem) Returns the attribute with the given ID and natural language.
GetAttributeByIndex Gets the attribute at the specified index.
GetEnumerator Gets an enumerator that can be used to navigate through the record's list of ServiceAttributes.
GetHashCode
(Inherited from Object)
GetLanguageBaseList Gets the list of LanguageBaseAttributeId items in the service record.
GetMultiLanguageStringAttributeById Gets a String containing the value of the TextString service attribute with the specified ID, using the specified natural language.
GetPrimaryLanguageBaseItem Gets the primary LanguageBaseAttributeId item in the service record.
GetPrimaryMultiLanguageStringAttributeById Gets a String containing the value of the TextString service attribute with the specified ID, using the primary natural language.
GetType
(Inherited from Object)
ToByteArray Return the byte array representing the service record.
ToString
(Inherited from Object)

See Also