The Connectivity API enables developers to easily use the Bluetooth and NFC (Near Field Communication) mobile technologies.
Bluetooth is often used for short range communication at FM radio frequencies. It has good transfer speeds but requires validation processes to verify the target and sender using a shared secret so that pairing can occur. Once paired the devices are then bonded and can transfer data freely.
NFC is used for very short range communications, less than a few centimeters and usually with the devices touching. For this reason it is not useful for transferring large chunks of data, but short bursts over a few seconds are achievable. Because there is no need for pairing this allows a form of validation that can be used to set up alternative communication channels such as Bluetooth.
Bluetooth has a range of up to 100 meters depending on the class of the device. Class 1 is about 5 meters, Class 2 is about 10 meters and Class 3 about 100 meters.
The distances over which Bluetooth can operate means that there are risks of connecting to the wrong device or having another party eavesdropping on the channel. Bluetooth counters this risk by requiring that a shared secret is used to establish a "pairing" of the devices. Once the pairing is done and the devices are bonded then the devices will permanently remember each other until the link key (shared secret) is deleted.
We can illustrate some of the features of the Bluetooth QML Plugin if we examine some examples. A simple example is the QML Bluetooth Scanner Example, which searches for nearby Bluetooth devices and lists the device name and other details. No pairing is required so this represents a simple introduction to the API.
When the Scanner example starts the "Scanning" button at the top has a pulsing blueish background, this indicates that the startup state of the example is to run discovery with the minimalDiscovery mode set to true. The following code triggers the QBluetoothDiscoveryModel object creation and the creation of the platform appropriate 'agent'. This initiates the discovery process.
BluetoothDiscoveryModel { id: myModel minimalDiscovery: true onDiscoveryChanged: busy.running = discovery; // onNewServiceDiscovered: console.log("Found new service " + service.deviceAddress + " " + service.deviceName + " " + service.serviceName); // uuidFilter: "e8e10f95-1a70-4b27-9ccf-02010264e9c9" }
If the bottom button with id fullButton (Full Discovery) is clicked the button_click() function is called. This toggles the value of the minimalDiscovery attribute and calls setDiscovery() with a true value.
function button_clicked() { myModel.minimalDiscovery = !myModel.minimalDiscovery; fullbutton.state = fullbutton.state == "clicked" ? "" : "clicked"; myModel.setDiscovery(true); }
The results of the discovery are managed by a ListView which uses the del component as its delegate. Each list element displays as a Bluetooth icon and device details including the device name.
ListView { id: mainList width: top.width anchors.top: busy.bottom // anchors.bottom: top.bottom anchors.bottom: fullbutton.top model: myModel highlight: highlightBox delegate: del focus: true }
Other aspects of the Bluetooth component of the API are covered in the QML Bluetooth Tennis Demo. The demo comprises two bluetooth devices, previously paired, discovering each other and then playing a game of Pong with positional and other information being relayed live to the server device (the initiator of the game). The game uses the BluetoothDiscoveryModel, BluetoothSocket and BluetoothService elements.
Near Field Communication(NFC) has a range of only about a centimeter. It can therefore be used as a contact based method of validation or discovery for other communications channels, often in the form "Touch to Play".
The NFC part of the Connectivity API provides QML elements to communicate peer-to-peer using LLCP sockets ( NearFieldSocket ), NDEF records of various types that encapsulate messages, a filtering mechanism on messages and The NearField element that starts the process.
Declaring a NearField element results in the creation of supporting objects include platform specific features. In the QML Poster Example, a NearField element is declared with id nearfield. This includes a filter constructed from two NdefFilters. The filters have the type specified by a string such as "urn:nfc:wkt:U", which identifies the type as being an NFC Well Known Type, that is predefined, of "U" representing a URL. The other NdefFilter element is for a Well Known Type of "T" (Text).
filter: [ NdefFilter { type: "urn:nfc:wkt:U"; minimum: 1; maximum: 1 }, NdefFilter { type: "urn:nfc:wkt:T"; minimum: 1 } ]
The NearField element has the properties of filter, messageRecords and orderMatch. The filter is a list of NdefFilter elements. The orderMatch property is a boolean that indicates if the order of the records in the filter is important, in the example this property is not used. The messageRecords property is a list of NdefRecords containing the results of the last read. When the signal messageRecordsChanged() is emitted the slot onMessageRecordsChanged can iterate through the messageRecords list selecting particular types. In the example, after all records in the messageRecords list have been examined the state of the example is set to "Show" which displays the results.
onMessageRecordsChanged: { posterText.text = ""; posterImage.source = ""; posterUrl.text = ""; var currentLocaleMatch = NdefTextRecord.LocaleMatchedNone; var i; for (i = 0; i < messageRecords.length; ++i) { if (messageRecords[i].recordType == "urn:nfc:wkt:T") { if (messageRecords[i].localeMatch > currentLocaleMatch) { currentLocaleMatch = messageRecords[i].localeMatch; posterText.text = messageRecords[i].text; } } else if (messageRecords[i].recordType == "urn:nfc:wkt:U") { posterUrl.text = messageRecords[i].uri; } else if (messageRecords[i].recordType.substr(0, 19) == "urn:nfc:mime:image/") { posterImage.source = messageRecords[i].uri; } } root.state = "show"; }
We have not covered the NearFieldSocket element. This is not used in the poster example, however in the QML Tennis Demo we see the use of the element in the handover code from NFC to Bluetooth. The code here shows the socket element and the slot onDataAvailable which parses the text payload of the application message. The uri identifies the service that the client is connecting to or the service that the server is registering.
NearFieldSocket { id: socket uri: "urn:nfc:sn:com.nokia.qtmobility.tennis" connected: true function parse(s) { var args = s.split(" "); if (args.length == 2) { bluetoothService.deviceAddress = args[0]; bluetoothService.servicePort = args[1]; root.bluetoothServiceChanged(); } } onDataAvailable: parse(socket.stringData) onStateChanged: { if (state == "Connecting") { available = true; } } }
The BluetoothDiscoveryModel element provides access device and service scanning | |
The BluetoothService element contains all the information available for a single bluetooth service.. | |
The BluetoothSocket element represents a single bluetooth client socket. | |
The NdefFilter element represents a filtering constraint for NDEF message records. | |
The NdefRecord element represents a record in an NDEF message. | |
The NdefTextRecord element represents an NFC RTD-Text NDEF record. | |
The NdefUriRecord element represents an NFC RTD-URI NDEF record. | |
The NearField element provides access to NDEF messages stored on NFC Forum tags. | |
The NearFieldSocket element represents an LLCP socket. |