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.

Monday, September 3, 2012

Use PHP, MySql and Google Map API v3 for displaying data on map

http://tips4php.net/2010/10/use-php-mysql-and-google-map-api-v3-for-displaying-data-on-map/Displaying data on maps can be useful in many situations.
By integrating tools like PHP, MySQL and Google Maps, you can relatively easy build customized maps for your website or blog.

In this post we’ll take a closer look on the possibilities, and build a  interactive map based on PHP, MySql and Google Map API v3.

Geocoded data

The script in this post uses MySQL for storing the data that’s going to be displayed on the map. This method works fine if you’re adding multiple points to your map (10+), and want a dynamic way to retrieve data data. If you’re going to display less than 10 Points the solution in this post is a little overkill.

Before proceeding, you need some geocoded data (data that contains lat/long information) to display on the map. If you don’t have geocoded data, you can find a post here, where you can learn how to geocode addresses for usage on eg. Google Maps.
You can use the following test data for this example:

01CREATE TABLE IF NOT EXISTS `poi_example` (
02 `id` int(11) NOT NULL AUTO_INCREMENT,
03 `name` text NOT NULL,
04 `desc` text NOT NULL,
05 `lat` text NOT NULL,
06 `lon` text NOT NULL,
07 PRIMARY KEY (`id`)
08) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
09 
10--
11-- Data dump for the table `poi_example`
12--
13 
14INSERT INTO `poi_example` (`id`, `name`, `desc`, `lat`, `lon`) VALUES
15(1, '100 Club', 'Oxford Street, London  W1&lt;br/&gt;3 Nov 2010 : Buster Shuffle&lt;br/&gt;', '51.514980', '-0.144328'),
16(2, '93 Feet East', '150 Brick Lane, London  E1 6RU&lt;br/&gt;7 Dec 2010 : Jenny &amp; Johnny&lt;br/&gt;', '51.521710', '-0.071737'),
17(3, 'Adelphi Theatre', 'The Strand, London  WC2E 7NA&lt;br/&gt;11 Oct 2010 : Love Never Dies', '51.511010', '-0.120140'),
18(4, 'Albany, The', '240 Gt. Portland Street, London  W1W 5QU', '51.521620', '-0.143394'),
19(5, 'Aldwych Theatre', 'Aldwych, London  WC2B 4DF&lt;br/&gt;11 Oct 2010 : Dirty Dancing', '51.513170', '-0.117503'),
20(6, 'Alexandra Palace', 'Wood Green, London  N22&lt;br/&gt;30 Oct 2010 : Lynx All-Nighter', '51.596490', '-0.109514');
When you have a MySQL database with Geocoded content you’re ready to proceed.

Extracting from MySQL

Next thing is to create a small piece of PHP that can connect and extract data from MySQL
01// connection to mysql
02 
03<?
04$dbname            ='<database name>'; //Name of the database
05$dbuser            ='<database username>'; //Username for the db
06$dbpass            ='<database password>'; //Password for the db
07$dbserver        ='<database server>'; //Name of the mysql server
08 
09$dbcnx = mysql_connect ("$dbserver", "$dbuser", "$dbpass");
10mysql_select_db("$dbname") or die(mysql_error());
11?>
12 
13// extracting and looping through data
14 
15<?
16 $query = mysql_query("SELECT * FROM poi_example");
17 while ($row = mysql_fetch_array($query)){
18 $name=$row['name'];
19 $lat=$row['lat'];
20 $lon=$row['lon'];
21 $desc=$row['desc'];
22echo ("addMarker($lat, $lon,'<b>$name</b><br/>$desc');\n");
23 }
24 ?>
As you can see, the output of the script is has the following format: “addMarker(lat, long, marker data);“, this is the marker format that you can use for adding multiple markers fir Google Maps API V3.

Google Maps API V3

Next thing is to embed the PHP code into the javascript required for displaying multiple infowindows in Google Map API V3.
For this example, we have used the code from August LI as inspiration.
The script has the following features:
  • “var icon”: specifies a customizable icon. In this example a icon from Google is used, but you can add your own icons as well
  • “var popup”: specifies the maximum width of the info window. In this case 300 pixels
  • “addMarker”: contains latitude and longitude of the points, and a possibility to display whatever HTML content you like in the info window that corresponds to each point.   In this example we’re just displaying a headline and description
  • The map automatically zooms and centers to the most detailed view where all the map markers can be displayed in the same map. This is automatically calculated based on the size of the map, and the locations of the map markers.
The most important limit of this script is, that this technique is primarily useful to display a limited amount of map markers (below 100). If you’re going to display more points, you should consider a marker cluster solution.
The final script with the PHP and javascript code merged looks like this:
01<?
02$dbname            ='insert mysql database name'; //Name of the database
03$dbuser            ='insert mysql user name'; //Username for the db
04$dbpass            ='insert mysql password'; //Password for the db
05$dbserver          ='insert mysql database server address'; //Name of the mysql server
06 
07$dbcnx = mysql_connect ("$dbserver", "$dbuser", "$dbpass");
08mysql_select_db("$dbname") or die(mysql_error());
09?>
10<html>
11 <head>
12 <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
13 <title>Google Map API V3 with markers</title>
14 <style type="text/css">
15 body { font: normal 10pt Helvetica, Arial; }
16 #map { width: 350px; height: 300px; border: 0px; padding: 0px; }
17 </style>
18 <script src="http://maps.google.com/maps/api/js?v=3&sensor=false" type="text/javascript"></script>
19 <script type="text/javascript">
20 //Sample code written by August Li
21 var icon = new google.maps.MarkerImage("http://maps.google.com/mapfiles/ms/micons/blue.png",
22 new google.maps.Size(32, 32), new google.maps.Point(0, 0),
23 new google.maps.Point(16, 32));
24 var center = null;
25 var map = null;
26 var currentPopup;
27 var bounds = new google.maps.LatLngBounds();
28 function addMarker(lat, lng, info) {
29 var pt = new google.maps.LatLng(lat, lng);
30 bounds.extend(pt);
31 var marker = new google.maps.Marker({
32 position: pt,
33 icon: icon,
34 map: map
35 });
36 var popup = new google.maps.InfoWindow({
37 content: info,
38 maxWidth: 300
39 });
40 google.maps.event.addListener(marker, "click", function() {
41 if (currentPopup != null) {
42 currentPopup.close();
43 currentPopup = null;
44 }
45 popup.open(map, marker);
46 currentPopup = popup;
47 });
48 google.maps.event.addListener(popup, "closeclick", function() {
49 map.panTo(center);
50 currentPopup = null;
51 });
52 }
53 function initMap() {
54 map = new google.maps.Map(document.getElementById("map"), {
55 center: new google.maps.LatLng(0, 0),
56 zoom: 14,
57 mapTypeId: google.maps.MapTypeId.ROADMAP,
58 mapTypeControl: false,
59 mapTypeControlOptions: {
60 style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR
61 },
62 navigationControl: true,
63 navigationControlOptions: {
64 style: google.maps.NavigationControlStyle.SMALL
65 }
66 });
67 <?
68 $query = mysql_query("SELECT * FROM poi_example");
69 while ($row = mysql_fetch_array($query)){
70 $name=$row['name'];
71 $lat=$row['lat'];
72 $lon=$row['lon'];
73 $desc=$row['desc'];
74 echo ("addMarker($lat, $lon,'<b>$name</b><br/>$desc');\n");
75 }
76 ?>
77 center = bounds.getCenter();
78 map.fitBounds(bounds);
79 
80 }
81 </script>
82 </head>
83 <body onload="initMap()" style="margin:0px; border:0px; padding:0px;">
84 <div id="map"></div>
85 </html>
The final result looks like this: