Programming Java 2 Micro Edition for Symbian OS 2004 (779882), страница 43
Текст из файла (страница 43)
The master–slaverole relates to the frequency hopping pattern used in RF communicationsbetween two Bluetooth devices. The master device initiates the connection and determines the frequency hopping pattern used. The slaves hopin unison to the master’s pattern. The role (master or slave) that a deviceassumes relates to low-level communication and is generally irrelevant tohigher level protocols. The current implementation of JSR 82 on SymbianOS supports only a value of false for the mustBeMaster parameter(true will result in an exception being thrown by the open() method).Once we have the connection URL we use it to open a Connection.In the case of connections using the SPP, the returned object is cast as aStreamConnection, as shown below.String url =serviceRecord.getConnectionURL(ServiceRecord.
NOAUTHENTICATE_NOENCRYPT,false);StreamConnection conn = (StreamConnection)Connector.open(url);OutputStream output = conn.openOutputStream();4.3.5 Connecting to a Service: the Quick and Dirty WayIn the previous section we described how to access services robustly.We do a device enquiry then search the returned devices for thePROGRAMMING THE BLUETOOTH APIs223required services and, if found, open a connection using the returnedServiceRecord.There is an alternative, quicker way of connecting to a service usingthe selectService() method of the DiscoveryAgent class:public String selectService(UUID uuid, int security, boolean master)This method simply takes the UUID of the service required; an intindicating the level of security for the connection; and the master/slaveboolean indicator. The method will search for the service denoted bythe UUID on any devices in range.
If the service is found, a Stringrepresenting the URL to be used to connect to the service via theopen() method is returned. If no service is found a value of null isreturned.Note that when using this method it is not necessary to implement aDiscoveryListener. Nor does it require a RemoteDevice object tobe specified. It simply searches all devices in the vicinity and, if one ofthem offers the required service, returns a connection URL.
If there aremany devices in the area offering the required service, a connection URLmay be returned to any one of them (it is not possible to specify which).For these reasons, plus the fact that this method takes only a single UUID,it is best used to search for specific UUIDs created to denote a specificservice (rather than pre-defined UUIDs representing generic services suchas the SPP, which may be offered by many devices).4.3.6 Retrieving a Cached DeviceBefore we leave this section we should discuss one other relevant methodprovided by the Java APIs for Bluetooth Wireless Technology. This is theretrieveDevices() method of the DiscoveryAgent class:public RemoteDevice[] retrieveDevices(int option)This takes an integer option argument that can have one of twovalues pre-defined in the DiscoveryAgent class:public static final int CACHEDpublic static final int PREKNOWN• CACHED means that the method will return an array of RemoteDevices that have been discovered by previous inquiries and cachedby the implementation; if no devices have been cached, a null valuewill be returned224JAVA APIs FOR BLUETOOTH WIRELESS TECHNOLOGY• PREKNOWN indicates a higher level of intimacy, referring to devicesthat the local device communicates with often (‘‘paired devices’’); thecurrent implementation of JSR 82 on Symbian OS does not supportthe PREKNOWN option, so a call to retrieveDevices using thePREKNOWN option will return null.The retrieveDevices() method will block the current thread until itreturns; it should generally be launched in a new Thread.4.4 L2CAP Protocol4.4.1 IntroductionThe discussion in the previous sections used Serial Port profile connections running over RFCOMM to illustrate opening connections.
In thissection we shall look at the other connection protocol currently offeredby Symbian OS, L2CAP.RFCOMM is a higher-level protocol that runs on top of L2CAP.Unlike SPP over RFCOMM, which is a stream-based protocol, L2CAPis packet-based. This makes it more suitable for certain types of nonstream communication, particularly those that route individual packetsto different destinations, methods or classes.
In addition, a lower level,datagram-like protocol such as L2CAP can confer performance advantages over RFCOMM by avoiding the latency and overheads involved inestablishing and maintaining a stream connection.4.4.2 Maximum Transmission UnitRemember that L2CAP is a packet-based protocol. The maximum transmission unit (MTU) is the maximum size of a packet of data that canbe sent over the L2CAP link.
By default this size is set to 672 bytes.However, the Java API does give us the option to specify different valuesas part of the connection URL passed into the open() method (as willseen in later sections). MTUs can be specified for transmitting and receiving data. Specifying MTU values when opening a connection does notmean that communication (whether sending or receiving) will take placeat that value. Instead, when a connection between a client and serveris opened, a negotiation takes place to agree on acceptable MTUs forcommunications in both directions.
The agreed MTU will be the lowestcommon denominator value that both parties can handle. For instance, ifa server can transmit a packet size of 4096 bytes but the client can onlyL2CAP PROTOCOL225receive a maximum packet size of 512 bytes, then the negotiated MTUwill be 512 bytes.It is possible to find out the maximum ReceiveMTU that the localdevice will support using the following code:localDevice.getProperty(“bluetooth.l2cap.receiveMTU.max”);On Symbian OS Version 7.0s, the maximum values for TransmitMTUand ReceiveMTU are both 672 bytes (the default values).
We can alsofind out the negotiated values for ReceiveMTU and TransmitMTU usingthe following methods of L2CAPConnection:public int getTransmitMTU()public int getReceiveMTU()For a more detailed discussion of MTUs see the JSR 82 specification.4.4.3 Setting up an L2CAP ServerSetting up a server for L2CAP is very similar to our earlier example usingthe SPP, except that an L2CAPConnection is opened in response toincoming client requests.L2CAPConnectionNotifier notifier =(L2CAPConnectionNotifier)Connector.open(url);L2CAPConnection conn = notifier.acceptAndOpen();Here url may have the following form:“btl2cap://localhost:00112233445566778899AABBCCDDEEFF;name=l2capServer”The name=l2capServer field is optional. Other optionalfields include ReceiveMTU and TransmitMTU (see the JSR 82 specification for a full list of options).
The open() method returns an instanceof L2CAPConnectionNotifier. Calling the acceptAndOpen()method on the L2CAPConnectionNotifier object indicates the serveris ready to accept client connections. It also adds the ServiceRecordto the SDDB. The acceptAndOpen() method blocks until the serveraccepts a connection request, returning an L2CAPConnection objectenabling communication to take place.2264.4.4JAVA APIs FOR BLUETOOTH WIRELESS TECHNOLOGYEstablishing a Client ConnectionTo obtain a connection to an L2CAP server, the process is very similarto that presented in earlier discussions using RFCOMM.
We can use aServiceRecord obtained by a service search to get the connectionURL via the getConnectionURL() method. We then use this in theopen() method to obtain an L2CAPConnection, as shown below.String url =serviceRecord.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT,false);L2CAPConnection conn = (L2CAPConnection)Connector.open(url);The url will have the general form:“btl2cap://0050CD00321B:1001;ReceiveMTU=512;TransmitMTU=512”Where 0050CD00321B is the Bluetooth address of the server and 1001is the Protocol Service Multiplexor value for the service which identifiesthe L2CAP service running on the device and allows the client to connectto the service.Again, there are various possible options for the url (check out theJSR 82 specification for more details). Note that if we wish to change theReceiveMTU or TransmitMTU we would have to edit the connectionURL before passing it to the open() method.Once we have obtained an L2CAPConnection we send a packetusing the send() method, where byte[] data contains the packet tobe sent:public void send(byte[] data)The size of data can have any value.