Showing posts with label Bluetooth. Show all posts
Showing posts with label Bluetooth. Show all posts

Sunday, September 16, 2012

Working with Bluetooth and GPS: Follow-up

After reading both Part 1 and Part 2 of the “Working with Bluetooth and GPS” series of articles, you were given a clear explanation of the example code that shows you how to do the following:

    1. Use the JSR-82 Bluetooth API to access the data from a Bluetooth-enabled GPS receiver

    2. Parse the data streams in NMEA format and obtain the coordinates of your current location

    3. Formulate an HTTP request to access an external mapping service

    4. Use the JSR-172 XML Parsing and Web Services API to parse an XML result

    5. Make a request in order to display a map image
Therefore, the purpose of this tech tip is to provide answers to the questions that were submitted by the readers of both articles in the series.
https://blogs.oracle.com/mobility_techtips/entry/working_with_bluetooth_and_gps1
Question 1: Hi Bruce, I have a problem when I start the Mpowerplayer tool with any MIDlet that uses Bluetooth and the JSR-82 API. When the application tries to execute my MIDet, it immediately displays a java.lang.NoClassDefFoundError: javax/bluetooth/DiscoveryListener. What could be the problem?
Answer 1: The MPowerplayer made a change on how it handles JSR-82 libraries between releases #1127 and #1185. Unfortunately, it not explicitly stated in the documentation, but you need to make two simple changes in order to run MIDlets that require the JSR-82 API:

    1. Place any JSR-82 implementation in the /mpp-sdk folder. I’ve tested with the following JSR-82 implementations: Avetana (requires a license) and BlueCove (free open-source alternative).

    2. Rename that file to be called bt.jar.
After you make those two changes, you will be able to run any application requires the JSR-82 APIs.
Question 2: Hi Bruce, this is a nice article. I would like to know how to get GPS data from a mobile phone that already has a GPS receiver built-in.
Answer 2: If your mobile phone is MSA-compliant and already has a GPS radio built-in, then you don’t need to use the JSR-82 API to connect to a remote GPS receiver. All you need to do is use the JSR-179 Location APIs in order to retrieve your location data from an embedded GPS receiver. If you’d like to get started with the JSR-179 API, then Qusay Mahmoud has written a great article, Java ME and Location-Based Services, on that topic.

Question 3: I have a Bluetooth-enabled GPS receiver: the Holux Slim 236. I also have a Bluetooth-enabled computer. Can I run this example with what I have?


Answer 3: Yes, you should have no problem running the example code using the tools that you have. If you plan to use the current version of Mpowerplayer, then be sure to follow the instructions in the answer to Q1 first.

Question 4: Hi Bruce, thanks for creating this meaningful guide for developers. Your original article shows developers how to use the Avetana Bluetooth JSR-82 implementation with the Mpowerplayer SDK. The problem, however is that Aventana implementation only provides a free 14-day trial, and afterwards requires a license fee. Is there any way to configure the Mpowerplayer with the BlueCove JSR-82 implementation which is open source?

Answer 4: Yes, please refer to the answer provided to Q1 listed above in order to find out how to use the BlueCove library with the MPowerplayer SDK.


Question 5: Hi, I am having problem with this example with WTK 2.5.2 and NetBeans IDE 6.1 which are both installed in my PC. When I run this application on my PC, I’m not able to get any data from the remote Bluetooth devices.

Answer 5: Actually, the whole point of Part 1 in the two-part series was to show developers how to debug and test their JSR-82 applications on their PCs using the Mpowerplayer. Neither the WTK, the NetBeans IDE, nor the Java ME SDK have the ability to leverage the Bluetooth hardware of your PC in order to discover or search for services on remote Bluetooth devices.


Question 6: I have a Bluetooth-enabled phone with a built-in GPS receiver. I want to send NMEA data from the phone to a Bluetooth-enabled PC. I have a desktop application (Streets & Trips) that can consume GPS data. Since my phone support GPS and Bluetooth, is there a Java ME application that will enable my mobile phone to do this?


Answer 6: I don’t know of any Java ME applications that do this, however this sounds like the basis for another article!

Final Thoughts
Thanks to all the readers who took the time to provide feedback to this article series! Your input, thoughts, questions, and ideas are always welcome and appreciated.

Link: https://blogs.oracle.com/mobility_techtips/entry/working_with_bluetooth_and_gps1

Wednesday, September 12, 2012

Working with Bluetooth and GPS: Part 2 - Parsing GPS Data and Rendering a Map

This article is the second of a two-part series on how to use Java ME technology and Bluetooth to access location data from wireless GPS devices.
Contents
 
Parsing the NMEA Sentences
Requesting a Map Image from an External Map Service
Parsing the XML Result from the Map Service
Conclusion
 
As you may recall from Part 1 of this series, it is very easy to access the raw GPS data from a Bluetooth-enabled GPS device. The listing below shows what the serial output from a typical GPS device would look like:
Listing 1. NMEA Formatted GPS Data
$GPGSV,3,3,10,31,76,012,31,32,60,307,38,,,,,,,,*72
$GPGSA,A,3,32,31,16,11,23,,,,,,,,4.5,3.1,3.3*34

$GPRMC,122314.000,A,3659.249,N,09434.910,W,0.0,0.0,220908,0.0,E*78
$GPGGA,122314.000,3659.24902,N,09434.91042,W,1,05,3.1,261.51,M,-29.1,M,,*58

$GPGSV,3,1,10,01,62,343,00,11,14,260,34,14,35,079,27,16,29,167,28*73
$GPGSV,3,2,10,20,44,309,00,22,13,145,00,23,08,290,31,30,23,049,33*7C
$GPGSV,3,3,10,31,76,012,31,32,60,307,38,,,,,,,,*72
$PSTMECH,32,7,31,7,00,0,00,0,14,4,30,4,16,7,00,0,11,7,23,7,00,0,00,0*50

$GPRMC,122315.000,A,3659.249,N,09434.910,W,0.0,0.0,220908,0.0,E*79
$GPGGA,122315.000,3659.24902,N,09434.91048,W,1,05,3.1,261.61,M,-29.1,M,,*50
 
As you also may recall from Part 1, a GPS device encodes its data according to the NMEA specification. The purpose of this article is to learn how to accomplish the following tasks:
  • Parse the NMEA sentence data from a GPS device to retrieve the latitude and longitude values
  • Request a map image of our current location from a external map service
  • Parse the XML result data from the map service and render the map image on the mobile device
Parsing the NMEA Sentences
The serial data that is produced by GPS devices is formatted according to the NMEA specification, and each line of data is called an NMEA sentence. There are at least 5 NMEA sentences that provide the coordinates of your current position. The good news is that I only need to create a parser for one of them. I'll choose the $GPGGA header for the purposes of this article. If you want to know more about all the various standard and non-standard NMEA sentences, refer to the NMEA FAQ website. Following is an example of what an ordinary $GPGGA sentence would look like:
$GPGGA,123519,4807.038,N,01131.324,E,1,08,0.9,545.4,M,46.9,M, ,;
 
After further inspection, you can now see that the individual parts of an NMEA sentence are separated by commas. The following facts can be obtained from the preceding NMEA sentence:
  • the GPS fix was taken at 12:35:19 UTC time
  • the latitude coordinate is 48 degrees and 07.038 minutes North
  • the longitude coordinate is 11 degrees and 31.234 minutes East
  • the GPS fix quality is 1
  • 8 GPS satellites were being tracked
  • the horizontal dilution of position was 0.9
  • the altitude of the GPS fix was 545.4 meters
  • the height of the geoid was 46.9 meters
Now, you'd think that it would be really easy for Java ME devices to parse the NMEA sentence using the StringTokenizer class, right? Unfortunately, it's not that easy since the StringTokenizer class only exists in Java SE implementations. However, in the example code I've included a simple NMEA parser and String tokenization classes. The following is a code snippet from Parser.java that properly converts coordinate DMS format (degrees, minutes, seconds) to decimal degree values.
Listing 2. Code Snippet from Parser.java
if (token.endsWith("$GPGGA")) {
    type = TYPE_GPGGA;

    // Time of fix
    tokenizer.next();

    // Latitude
    String raw_lat = tokenizer.next();
    String lat_deg = raw_lat.substring(0, 2);
    String lat_min1 = raw_lat.substring(2, 4);
    String lat_min2 = raw_lat.substring(5);
    String lat_min3 = "0." + lat_min1 + lat_min2;
    float lat_dec = Float.parseFloat(lat_min3)/.6f;
    float lat_val = Float.parseFloat(lat_deg) + lat_dec;

    // Latitude direction
    String lat_direction = tokenizer.next();
    if(lat_direction.equals("N")){
        // do nothing
    } else {
        lat_val = lat_val * -1;
    }

    record.latitude = lat_val + "";

    // Longitude
    String raw_lon = tokenizer.next();
    String lon_deg = raw_lon.substring(0, 3);
    String lon_min1 = raw_lon.substring(3, 5);
    String lon_min2 = raw_lon.substring(6);            
    String lon_min3 = "0." + lon_min1 + lon_min2;
    float lon_dec = Float.parseFloat(lon_min3)/.6f;
    float lon_val = Float.parseFloat(lon_deg) + lon_dec;
    
    
    // Longitude direction
    String lon_direction = tokenizer.next();
    if(lon_direction.equals("E")){
        // do nothing
    } else {
        lon_val = lon_val * -1;
    }
    record.longitude = lon_val + "";

    record.quality = tokenizer.next();

    record.satelliteCount = tokenizer.next();
    record.dataFound = true;
    // Ignore rest
    return 200;
}
 
Now that we've properly parsed the NMEA sentence, let's explore how to get a map using an external mapping service.
Requesting a Map Image from an External Map Service
In this day and age, you have several options to choose from when you want to make a simple HTTP request to get an image that represents a map of your current location (or any location for that matter). Several companies -- Mapquest, Google, and ERSi -- provide these services, but I decided to use the Yahoo! Maps service for the following reasons:
  1. All the options can be specified in URL parameters in a single HTTP request.
  2. No external libraries are needed to consume the API.
  3. The response comes back as simple XML document that can be easily parsed.
  4. The resulting map image is in PNG format, which all MIDP devices support.
In order to use the Yahoo! Maps API, all you need to do is sign up for a free developer account id key. So, if I wanted a map with the following parameters:
  • latitude: 46.987484
  • longitude: -84.58184
  • image width: 400 pixels
  • image height: 400 pixels
  • zoom level: 7
then the URL in the HTTP request would look like this:
http://local.yahooapis.com/MapsService/V1/mapImage?appid=
YOUR_YAHOO_ID_KEY&latitude=46.987484&longitude=-
84.58184&image_width=400&image_height=400&zoom=7
 
Pretty simple, huh? The result of this request is not the image itself, but an XML document that has a link to the image. The listing below shows the XML result of my HTTP request for a map image:
Listing 3. XML Result from the Yahoo! Maps Service
<?xml version="1.0"?>
<Result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
http://gws.maps.yahoo.com/mapimage?MAPDATA=Voo4MOd6wXXT6pG.WpNC6XPETWAN8WDUsxa
8qRQ2kzC_f8vO7.FvQhW3hSbWbF_jO3H4.J2Gb7Qhc2vqoCTL0DWbaCfT751_Zt9Ysqtg0dKo2mv95
EIc4bbgdYrmebNqFcwfKb8YhOFe38Ia3Q--&mvt=m?cltype=onnetwork&.intl=us
</Result>
 
Parsing the XML Result from the Map Service
Ok, we're almost at the finish line. All we need to do now is to parse the result that we got from the map service and extract the URL to the map image. Fortunately, this is also a trivial task thanks to the JSR-172 XML Parsing API.
You should also be glad to know that the JSR-172 API has been out for several years and is available on a wide variety of mobile handsets. Of course, the JSR-172 API is a part of the Java ME MSA standard, so if your handset supports MSA then you're obviously good to go.
In the following listing, you can see that my XML parsing class only needed to extend the DefaultHandler class in the JSR-172 API. Since we're only interested in the contents of a single tag, namely the <Result> tag, then the code necessary to retrieve the URL for the map image is fairly simple.
Listing 4. A Simple XML Parsing Class Using the JSR-172 API
public class SimpleHandler extends DefaultHandler {
    
    public String image_url = null;
    
    public SimpleHandler() {}

    public void startDocument() throws SAXException {}
 
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

        if(qName.equals("Result")) {
		// do nothing
        } else {
            throw new SAXException("<Result> tag not found");
        }
    }
   
    public void characters(char[] ch, int start, int length) throws SAXException {
        image_url = new String(ch, start, length).trim();
    }
 
  public void endElement(String uri, String localName, String qName, Attributes attributes) throws SAXException{}
 
  public void endDocument() throws SAXException{}    
  
  public String getImageURL(){
      return image_url;
  }        
}
 
Now the code in Listing 4, specifically the getImageURL() method, will return the URL that points to the PNG image of the map of our current location. The only remaining step is to make another HTTP request to retrieve the image and display it on the mobile device. Figure 1 depicts a mobile device showing our current location.

Link : http://dsc.sun.com/mobility/apis/articles/bluetooth_gps/part2/

Sunday, September 9, 2012

Working with Bluetooth and GPS: Part 1 - Reading Wireless Serial Port Data

For some developers, working with wireless technologies can be daunting -- and sometimes downright intimidating. All communication is wireless, so you can't just "look up" and see, for instance, 1 MB of data going by. In addition, it is really difficult to debug wireless applications once they are deployed to a mobile device, since you don't have access to system traces or log files to pinpoint the errors while the application is running.
This technical article addresses the following tasks:
  • Helps demystify some wireless concepts using Bluetooth and the JSR-82 API
  • Shows how to run and debug Java ME Bluetooth applications on your desktop computer
  • Explains how to read data from a Bluetooth-enabled GPS device
Contents
 
The Big Problem: Where Emulators Fail
Setting Up the Environment
Unraveling Some Mysteries of Bluetooth and JSR-82
Summary
 
 
I love using the Sun Wireless Toolkit for CLDC. It is a great tool, and it's very handy when I need to create Java ME applications that adhere to the latest and greatest Java ME JSR specifications. However, the Java ME emulator in the Sun Wireless Toolkit has no means to access or communicate with actual Bluetooth hardware, which means that I don't have the ability to fully test my application with the Sun Wireless Toolkit after I start to make API calls that rely on functioning Bluetooth hardware. Because of this problem, developers are left in a difficult situation when they need to develop, test, and debug JSR-82 applications.
Additionally, testing your Java ME Bluetooth applications directly on your JSR-82 device is impractical since you don't have access to the System.out for simple debugging of your application. Additionally, the iteration cycles for developing, compiling, provisioning, and installing the application on a mobile phone is very time consuming.
The good news is that you're going to learn how to construct a low-cost solution that allows you to install, debug, and test your JSR-82 applications on your computer. I'm going to introduce to you the Mpowerplayer, a CLDC emulator for the computer that can be configured to behave like a JSR-82 Bluetooth-enabled phone. With this configuration, the Mpowerplayer will behave just like a JSR-82 Bluetooth-enabled mobile phone, but you'll have access to the System.out and have the ability to view stacktraces, both of which are essential in debugging your wireless application.

 
The following list shows the materials that you need to run the example code provided later in this article:
  • Required

    • The Sun Wireless Toolkit for CLDC. This tool is the defacto standard for developing Java ME applications.
    • A Bluetooth-enabled computer. The Bluetooth module for your PC could either be built-in to the computer or can be attached externally via the USB port.
    • The Mpowerplayer. This free desktop application is a very good mobile emulator. It is able to access your Bluetooth hardware on your desktop PC, to execute the JSR-82 method calls that require access to actual Bluetooth hardware.
    • REQUIRED - A JSR-82 library that supports the Mpowerplayer. I use the Avetana SDK, which works beautifully with the Mpowerplayer.
    • A Bluetooth-enabled GPS device. I use the DeLorme Earthmate BT-20.
  • Optional

    • A Java ME phone that supports the JSR-82 API. If you don't know whether your phone supports the JSR-82 API, be sure take a look at this list. It is the best source of information to determine what Java ME APIs the major phone manufacturers support. However, I did notice that the list didn't include any RIM Blackberry devices, which also support the JSR-82 specification.
The developer version of the Mpowerplayer is available as a zip file. All you need to do is unzip the file in the location that you desire to install it. Now, for the Mpowerplayer to get access to the Bluetooth device on your PC, copy the avetanaBluetoth.jar file to the "mpp-sdk\bluetooth" folder - it's just that simple! Later on, you're going to see screenshots of Mpowerplayer in action.

 

Did you know that once you discover the connection URL for your desired Bluetooth service, then you no longer need to employ the device- and service-discovery processes? If you're unfamiliar with what a Bluetooth connection URL looks like, I have provided an example below:
btspp://001AA3000C19:1;authenticate=false;encrypt=false;master=false
Let us briefly revisit the purposes of the device-discovery and service-discovery processes that apply to all Bluetooth-enabled systems, whether or not if you use the JSR-82 API. The device-discovery process is used to determine what Bluetooth devices are in the vicinity. In the connection URL listed previously, the device represented has the Bluetooth address of 001AA3000C19. In the example code that will be presented later in this article, I used an inner class named BTUtility that implements all the necessary JSR-82 Bluetooth API code for device and service discovery. The code snippet below shows the necessary steps for device discovery:
        public BTUtility() {
            try {
                LocalDevice localDevice = LocalDevice.getLocalDevice();
                discoveryAgent = localDevice.getDiscoveryAgent();
                discoveryForm.append(" Searching for Bluetooth devices in the vicinity...\n");
                discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);

            } catch(Exception e) {
                e.printStackTrace();
            }
        }

        public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass cod) {
            try{
 		   discoveryForm.append("found: " + remoteDevice.getFriendlyName(true));
            } catch(Exception e){
               discoveryForm.append("found: " + remoteDevice.getBluetoothAddress());
            } finally{
		   remoteDevices.addElement(remoteDevice);
		}
        }

        public void inquiryCompleted(int discType) {

            if (remoteDevices.size() > 0) {

                // the discovery process was a success
                // so let's out them in a List and display it to the user
                for (int i=0; i<remoteDevices.size(); i++){
                    try{
                       devicesList.append(((RemoteDevice)remoteDevices.elementAt(i)).getFriendlyName(true), bt_logo);
                    } catch (Exception e){
                       devicesList.append(((RemoteDevice)remoteDevices.elementAt(i)).getBluetoothAddress(), bt_logo);
                    }
                }
                display.setCurrent(devicesList);
            } else {
			// handle this
		}
 
The inner class itself implements the DiscoveryListener interface, so its deviceDiscovered() method will be called every time a remote Bluetooth device has been found. When the device-discovery process has finally ended, the JVM will call the inquiryCompleted() method. Fortunately, I don't have to deploy this application to my JSR-82 enabled phone to properly test it. I can test the entire application on my desktop computer using the Mpowerplayer, as described earlier.

Figure 1 shows the Mpowerplayer running my application during the device-discovery process, and Figure 2 shows the state of mobile application after the device-discovery process is finished.

Now that we've taken care of the device-discovery process, and we see that the device that we want to connect to is in the list of available devices, let's take another look at the fully qualified connection URL.
btspp://001AA3000C19:1;authenticate=false;encrypt=false;master=false
As you can see, the device-discovery process lets us know the Bluetooth address (in this case, 001AA3000C19) and the friendly name of the remote Bluetooth device (in this case, Earthmate BT-20 GPS). But we still don't know what the other parameters are that comprise the connection URL. After all, a single Bluetooth device can offer multiple services -- for instance, a Bluetooth Access point can offer both Dialup Networking and Personal Area Networking services. Therefore, we need to search for the appropriate service that we want on the selected Bluetooth device.

The service-search process is dependent on knowing the type of service that you want. I want to consume serial data from a Bluetooth-enabled GPS device, and the unique identifier for wireless serial services is 0x1101. The previously mentioned inner class, BTUtility, has also implemented all the code for service searching. The following snippet shows what is involved.
        public void run(){

            try {
                RemoteDevice remoteDevice = (RemoteDevice)remoteDevices.elementAt(devicesList.getSelectedIndex());
                discoveryAgent.searchServices(attrSet, uuidSet, remoteDevice , this);

            } catch(Exception e) {
                e.printStackTrace();
            }
        }

        public void servicesDiscovered(int transID, ServiceRecord[] servRecord){

            for(int i = 0; i < servRecord.length; i++) {

                DataElement serviceNameElement = servRecord[i].getAttributeValue(0x0100);
                String _serviceName = (String)serviceNameElement.getValue();
                String serviceName = _serviceName.trim();
                btConnectionURL = servRecord[i].getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);

            }
            display.setCurrent(readyToConnectForm);
		readyToConnectForm.append("\n\nNote: the connection URL is: " + btConnectionURL);
		System.out.println("Note: the connection URL is: " + btConnectionURL);

        }

        public void serviceSearchCompleted(int transID, int respCode) {

            if (respCode == DiscoveryListener.SERVICE_SEARCH_COMPLETED) {
                // the service search process was successful

            } else {
                // the service search process has failed
            }

        }
 
Now, service searching is a blocking I/O operation, so I put the intensive work in the run() method of a thread to allow the application to behave nicely. Whenever a matching service has been found on the remote device, the JVM will call my servicesDiscovered() method to let me know so that I can do something about it. As shown in the following figure, I've found the service that I want, and I have everything that I need to get the connection URL.
 
To reiterate a previous point: now that you have determined the connection URL for your desired device, you no longer need to go through the device- and service-discovery processes for subsequent usage of the remote Bluetooth device. All you need to do is open a connection on the URL. After that, you have everything that you need to communicate with the remote Bluetooth device.
Figure 4 shows the operation of another thread-enabled inner class that opens the connection on the URL and then reads the data from the wireless serial port.
 
Wait a minute. If we're reading serial data from a GPS device, then where are the latitudes, longitudes, and other global-positioning stuff? Is the data corrupted?
Actually, the serial data that you see in Figure 4 is actually encoded in NMEA (National Marine Electronics Association) format, which is the common format for all GPS devices. Part 2 of this technical article shows you how to decode the NMEA data and plot your location on your phone.

Link: http://dsc.sun.com/mobility/apis/articles/bluetooth_gps/part1/

Thursday, September 6, 2012

Package de.avetana.bluetooth

Package de.avetana.bluetooth Description

This package provides an implementation of the JSR 82 specification from Sun Microsystems (c). The aim of this specification is to easily develop Bluetooth-based applications in java. It does not exist (as I am writing these comments) any universal implementation of the Sun Specification.
The Avetana Bluetooth package is available under three operating systems: Linux (GPL version), Windows and Mac OS X (commercial versions) and is NOT a 100 % pure Java implementation. The use of JNI technologies allows to communicate with the hardware and system-specific bluetooth stack.
Under Linux you must have a kernel version > 2.4.20 or at least you must have the BlueZ kernel modules installed AND loaded.

Package Specification

For JSR82-Specification, please see

Related Documentation

For overviews, examples, guides, and tool documentation, please see the API documentation and the documents stored in the directory named "doku".
The class de.avetana.bluetooth.JSRTest2 gives an overview of the possibilities offered by this implementation.
Please refer to the following tutorial, too.

Quick Tutorial

Management of the local Device

The JSR82 Specification allows to work only with one Local Device, which is accessible with the help of the static method:

LocalDevice m_local=LocalDevice.getLocalDevice();



You can now retrieve some properties of your local device:

//retrieves the BT address of the local device
LocalDevice.getBluetoothAdress()

//retrieves the name of the local device
LocalDevice.getFriendlyName()

// retrieves the discoverable mode. Beware, this method often requires root privileges
LocalDevice.getDiscoverableMode()


The method getRecord(ConnectionNotifier) and updateRecord(ServiceRecord) cannot be directly used here.
They suppose that you have already created a service waiting for incoming connections.

Device/Service Search

With your LocalDevice you can retrieve the DiscoveryAgent which will help you to perform an HCI inquiry (Device search) or a service Search.

//retrieves the DiscoveryAgent
DiscoveryAgent m_agent=LocalDevice.getDiscoveryAgent()

Whatever the search you want to perforn you need beside your DiscoveryAgent a DiscoveryListener.
The DiscoveryListener will set the way your application react each time a new device or a new service is found, but also when the searches terminate normally or abnormally.

Example of a device search

DiscoveryListener myListener=new DiscoveryListener() {
  public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
    //does nothing
  }

  public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
    try {
      System.out.println("New Device "+btDevice.getBluetoothAddress()+" found!");
      System.out.println("Remote Name of the device is "+btDevice.getFriendlyName(true));
    }catch(Exception ex) {}
  }

  public void inquiryCompleted(int discType) {
    System.out.println("Device Search completed!");
  }

  public void serviceSearchCompleted(int transID, int respCode) {
    // does nothing
  }
};

try {
   m_agent.startInquiry(DiscoveryAgent.GIAC, myListener);
}
catch(Exception ex) {ex.printStackTrace();}

This example does not implement the part of the DiscoveryListener class used to manage the result of a service search. In this case this does not have any influence, since this little code-fragment is only performing a device search.
A more complete example performing a service search as soon as the device search is completed can be found in the de.avetana.bluetooth.util.ServiceFinderPane class.

I strongly recommand to refer to this class for a pratical example.

Client connection and data exchange

After a service search and the choice of the service you want to connect to, you know the connection URL used to perform a client connection (this URL is given by the method javax.bluetooth.ServiceRecord#getConnectionURL(...)).

Let's suppose that the choosen service waits for RFCOMM protocol based-connections. The form of the URL is:

String connectionURL="btspp://123456123456:1;encrypt=false;authenticate=false;master=true"

To connect to this service, assuming that running is a class variable set to false, when the user presses an UI button labelled Close:

  Connection con=Connector.open(connectionURL);
  Runnable r=new Runnable() {
    public void run() {
      byte b[] = new byte[200];
         try {
            while (running) {
               dataReceived.setText("Received " + received);
               int a = is.read(b);
               received += a;
            }
         } catch (Exception e) {e.printStackTrace();running=false; }
    }
  //Starts the thread used to read data
  new Thread(r).run();

  //Write some data
  ((StreamConnection)streamCon).openDataOutputStream().writeChars("Try to write");

License

In each file related to this project, you will find the following header:

COPYRIGHT:
(c) Copyright 2004 Avetana GmbH ALL RIGHTS RESERVED.

This file is part of the Avetana bluetooth API for Linux.

The Avetana bluetooth API for Linux is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

The Avetana bluetooth API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

The development of the Avetana bluetooth API is based on the work of Christian Lorenz (see the Javabluetooth Stack at http://www.javabluetooth.org) for some classes, on the work of the jbluez team (see http://jbluez.sourceforge.net/) and on the work of the bluez team (see the BlueZ linux Stack at http://www.bluez.org) for the C code. Classes, part of classes, C functions or part of C functions programmed by these teams and/or persons are explicitly mentioned.

Please RESPECT the terms of this license and commit any changes!!!.

Conclusion

The JSR82 specification is really an easy-to-use development tool for Bluetooth. Moreover the use of the Avetana Bluetooth implementation is transparent for the end-programmer.

This quick tutorial has made a short presentation of the possibilities offered by the Avetana Bluetooth implementation but a look at the JSRTest class could complete this HOWTO.

Several turorials are available on the internet and I strongly suggest to consult them if you are not familiar with Bluetooth, Java or the use of JSR82.
But please keep two things in mind:
  • Only RFCOMM and L2CAP protocols are currently supported.
  • The linux implementation is free under the terms of the GPL. So if you want to modify some files, please do it and commit any modifications with our CVS Server.

Tuesday, August 28, 2012

Wireless Development Tutorial Part II

In Part I of this tutorial, you learned how to write a simple Java Platform, Micro Edition (Java ME) application. The application, a MIDlet, was designed for the Mobile Information Device Profile, one of the Java ME specifications. Now you're going to expand your horizons dramatically. You'll learn how to write and deploy a servlet, and then how to hook up a MIDlet with the servlet. By the time you finish reading this, you'll have all the tools you need to develop end to end wireless Java applications.
We are using Tomcat platform for servlet development.
  • Tomcat is the freely available reference implementation of the Java servlet and JavaServer Pages (JSP) specifications. Although it is not meant to be a production quality server, Tomcat is an excellent platform for developing and testing servlets.
There are pros and cons for using Tomcat server. Tomcat is easier to use for servlet development. However, its capabilities are limited to servlets and JSPs.


Installing and Running Tomcat
Tomcat is distributed as a ZIP archive, available from the Apache Jakarta project. For this writing, the version is 4.1.31.
Installation of Tomcat is simple: just unzip the download file. You can put it wherever you want. I unzipped it to a root-level directory, c:\jakarta-tomacat-4.1.31.
Tomcat itself is written in Java. To run Tomcat you'll need to tell it where to find your J2SE SDK installation. To do this, put the location of your J2SE SDK installation in the JAVA_HOME environment variable. On my machine, the variable has the value c:\jdk1.5.0_06.
To set the JAVA_HOME environment variable, go to Control Panel>System>Advanced>Environment Variables
To run Tomcat, open a command window. Change directories to Tomcat's bin directory. Type startup and stand back. A new window will open up and display copious initialization messages:
Tomcat's initialization messages
 
You can use a browser to test if Tomcat is really running. Try to open the URL http://localhost:8080/ and see what happens. If Tomcat is running correctly you'll see a default page from Tomcat with links to some servlet and JSP examples.
To shut down Tomcat, open another command window. Change directories to Tomcat's bin directory and run the shutdown command.
Starting and stopping Tomcat this way is a little clumsy. I recommend creating Windows shortcuts to run the startup and shutdown commands.
Writing Servlet Source Code
Writing the source code for your servlet is much like writing any other Java source code: use the text editor of your choice to create .java source files. In this example, you'll write a very simple servlet called HitServlet. Its source code is shown below. HitServlet simply counts the number of times it's been invoked and writes back to the client a message containing the count. (It's not thread-safe, but that doesn't matter here.)
import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;

public class HitServlet extends HttpServlet {
  private int mCount;
  
  public void doGet(HttpServletRequest request,
      HttpServletResponse response)
      throws ServletException, IOException {
    String message = "Hits: " + ++mCount;

    response.setContentType("text/plain");
    response.setContentLength(message.length());
    PrintWriter out = response.getWriter();
    out.println(message);
  }
}
 
Later, you're going to build a web application with a very specific directory structure. This directory structure makes it easy for the server to find the pieces of your application. For now, take it on faith and save the source code in a file under the Tomcat root directory named webapps/midp/WEB-INF/classes/HitServlet.java. (Go ahead and create the midp directory and its subdirectories now.)


Compiling the Servlet
Compiling servlet code is pretty much the same as for other Java development, except for an important twist. Because the servlet API is not a core part of the Java SE platform, you'll need to add it to your CLASSPATH before you can compile servlets.
The servlet API is contained in common/lib/servlet.jar under the Tomcat root directory. Simply add this file to your CLASSPATH and you will be able to compile HitServlet.java using javac. You can edit the CLASSPATH in the system properties or do it on the command line, as this Windows example demonstrates:
C:\>set CLASSPATH=\jakarta-tomcat-4.1.31\common\lib\servlet.jar

C:\>javac HitServlet.java
 


Deploying the Servlet
To deploy your servlet, you'll first need to understand something about web applications. A web application is a collection of static content, like HTML and image files, servlets, and other resources that can be made accessible via a web interface. Tomcat comes with several web applications already installed. Go look in the webapps directory under your Tomcat installation directory and you'll see a few: examples and webdav, for instance. We're going to create a new web application and place our servlet inside.
First, let's create the web application. You already created a new diretory inside webapps called midp, where you saved the servlet source code. Now you'll need to edit one of Tomcat's configuration files to tell Tomcat about the new web application. Open the conf/server.xml file with a text editor. In this file, web applications are called contexts. Scroll down to find the Context entry for the examples web application, which begins like this:
<!-- Tomcat Examples Context -->
<Context path="/examples" docBase="examples" debug="0"
         reloadable="true" crossContext="true">
 
Above or below this lengthy context entry (it's closed by </Context>, many lines down), create a new context entry for your new web application. It will look similar to the opening tag for the examples context, but you'll change the names to midp as appopriate and close the tag inline.
<!-- MIDP Context -->
<Context path="/midp" docBase="midp" reloadable="true"/>
 
Once you're finished adding the context entry, save the file.
What these steps do is map incoming HTTP requests to a web application in a particular directory. Specifically, any incoming HTTP request that begins with "/midp" (the path) will be handed off to the web application located at webapps/midp (the docBase). The reloadable attribute helps a lot with debugging; it tells Tomcat to reload automatically any servlet class you change so you don't have to restart the server.
Now that you've created a web application, fill it up. Web applications have a standard directory structure, mandated by the servlets specification. We won't get into too much detail here. The essential piece of a web application is a web.xml file that describes the various parts of the web application. This file lives in a standard location in every web application; it's always stored as WEB-INF/web.xml
It's time to create a web.xml file for your new application. You want to make the servlet accessible to the outside world. You know the class name of the servlet, HitServlet, and you'd like to make it available under a path like /hits. Note that the path for the servlet is relative to the path for the web application, so the full path to the servlet will be http://localhost:8080/midp/hits. Copy the following text (or download it) and save it as webapps/midp/WEB-INF/web.xml under the Tomcat root directory:
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  <servlet>
    <servlet-name>bob</servlet-name>
    <servlet-class>HitServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>bob</servlet-name>
    <url-pattern>/hits</url-pattern>
  </servlet-mapping>
</web-app>
 
This file tells Tomcat to map the servlet called HitServlet to the path /hits. The servlet-name is internal to web.xml; it links the servlet element to the servlet-mapping element. The name bob is only a friendly example; you can choose whatever name you want.
You recall that you had saved your servlet source code in a standard directory underneath WEB-INF called classes. This is where Tomcat expects to find servlet class files, so when you compiled the source code, the servlet class was stored in the right place.
Your servlet is now deployed in the new web application you created, but note that you must restart Tomcat to have it recognize the changes you made in server.xml.
To test your handiwork, go to a browser and navigate to http://localhost:8080/midp/hits. You should see the output of HitServlet. Reload the page a few times and watch the hit counter increase.
For more information on servlet development, see Java Servlet Technology, part of the J2EE Tutorial.


Hooking Up a MIDlet to the Servlet
This part is fun. Now that you have a development environment that supports both MIDP and servlets, you are going to hook the two worlds together to create an end to end Java application. MIDlets can connect to the world at large via HTTP, and the servlet you just wrote is available to the world at large via HTTP, so it's a pretty simple matter to have a MIDlet connect to the servlet.
Start KToolbar (part of the Sun Java Wireless Toolkit) and open the MIDlet project that you created in Part I of this tutorial. You're going to create a new MIDlet that connects to your servlet, retrieves its output, and displays it. If you haven't created a Sun Java Wireless Toolkit project yet, go back to Part I and do it now. The full source code for the MIDlet that connects to HitServlet is shown below.
import java.io.*;

import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public class HitMIDlet
    extends MIDlet 
    implements CommandListener {
  private Display mDisplay;
  private Form mMainForm;
  private StringItem mMessageItem;
  private Command mExitCommand, mConnectCommand;
  
  public HitMIDlet() {
    mMainForm = new Form("HitMIDlet");
    mMessageItem = new StringItem(null, "");
    mExitCommand = new Command("Exit", Command.EXIT, 0);
    mConnectCommand = new Command("Connect",
        Command.SCREEN, 0);
    mMainForm.append(mMessageItem);
    mMainForm.addCommand(mExitCommand);
    mMainForm.addCommand(mConnectCommand);
    mMainForm.setCommandListener(this);
  }
  
  public void startApp() {
    mDisplay = Display.getDisplay(this);
    mDisplay.setCurrent(mMainForm);
  }
  
  public void pauseApp() {}
  
  public void destroyApp(boolean unconditional) {}
  
  public void commandAction(Command c, Displayable s) {
    if (c == mExitCommand)
      notifyDestroyed();
    else if (c == mConnectCommand) {
      Form waitForm = new Form("Waiting...");
      mDisplay.setCurrent(waitForm);
      Thread t =  new Thread() {
        public void run() {
          connect();
        }
      };
      t.start();
    }
  }
  
  private void connect() {
    HttpConnection hc = null;
    InputStream in = null;
    String url = getAppProperty("HitMIDlet.URL");
    
    try {
      hc = (HttpConnection)Connector.open(url);
      in = hc.openInputStream();

      int contentLength = (int)hc.getLength();
      byte[] raw = new byte[contentLength];
      int length = in.read(raw);

      in.close();
      hc.close();

      // Show the response to the user.
      String s = new String(raw, 0, length);
      mMessageItem.setText(s);
    }
    catch (IOException ioe) {
      mMessageItem.setText(ioe.toString());
    }
    mDisplay.setCurrent(mMainForm);
  }
}
 
The main screen of HitMIDlet is similar to HelloMIDlet, but it includes two commands, Exit and Connect. Connect sets up a separate thread and calls the connect() method, which takes care of making a network connection and retrieving the results.
Copy the code above (or download it) into your editor. Save it as HitMIDlet.java inside the apps/HelloSuite/src directory underneath the Sun Java Wireless Toolkit root directory.
There are two other things to configure to get HitMIDlet working. First, you need to tell the toolkit about this new MIDlet. Click on Settings..., then select the MIDlets tab. Click on Add and fill in "HitMIDlet" for both the MIDlet name and class name. You can leave Icon blank. Click on OK and you should see both HelloMIDlet and HitMIDlet listed.
Next, you need to define a system property that HitMIDlet uses as the URL for its network connection. (This property is retrieved in the third line of the connect() method.) In the toolkit, click on Settings..., then select the User Defined tab. Click on the Add button. Fill in the property name as HitMIDlet.URL; the value should be the URL that invokes HitServlet, the same URL you used in a browser to test the servlet. When you're finished, click on OK to dismiss the project settings window.
Now, in the Sun Java Wireless Toolkit, click on Build to build the project. Assuming you don't see any error messages, you are now ready to test the application. Make sure your server is running first. Then click on Run and select HitMIDlet. Select the Connect command. If everything goes well, HitMIDlet will invoke HitServlet and display the results on the device emulator screen:

Link: http://www.oracle.com/technetwork/java/tutorial2-138827.html