Thursday, August 4, 2011

Bluetooth in J2ME :- Simple chat application

In previous tutorial , we learned about Bluetooth Device Discovery.

In this tutorial we will learn ,how to make simple bluetooth connection .In this we will implement the code in which approval for connection is not required by the sender. Reciever automatically recieves the sent text.


Here is the code for the Bluetooth Chat:-(2 .java files )

Client.java:-


import java.io.*;
import javax.bluetooth.*;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

/*
 * @author Vaibhav
 */
public class Client extends MIDlet implements CommandListener,DiscoveryListener,Runnable {

   
    private Display display;
    public List devicelist;
    private final List deviceList;
    public DiscoveryAgent agent;
    public String deviceName,address;
    private Command Refresh,connect,end,Exit;
    private String s,url;
    private Alert dialog1;
    private StreamConnection conn;
    private Server b;
    private DataOutputStream dos;
    private String[][] array[][] ;
    Thread t;
  
  
    public Form ChatForm = new Form("chat window");
    private Command send,exit;
    private TextField textfield;
    private String sendmsg;
 
   
    public Client()
    {
        deviceList = new List("List of Devices",List.IMPLICIT);
        Exit= new Command("Exit",Command.EXIT, 0);
        connect = new Command("connect",Command.SCREEN, 1);
        Refresh = new Command("Refresh",Command.SCREEN, 1);
        end = new Command("End",Command.EXIT, 1);
        deviceList.addCommand(Exit);
        deviceList.addCommand(connect);
        deviceList.addCommand(Refresh);
        deviceList.setCommandListener(this);
        Display.getDisplay(this).setCurrent(deviceList);
     
        t = new Thread(this);
    }
    public void startApp() throws MIDletStateChangeException {
        try {
            b=new Server(this);
            getChatForm();
            deviceList.deleteAll();
            LocalDevice local = LocalDevice.getLocalDevice();
            address = local.getBluetoothAddress();
            agent = local.getDiscoveryAgent();
            
        } catch (BluetoothStateException ex) {
            throw new MIDletStateChangeException("Unable to retrieve local Bluetooth device.");
        }
      
            }
   

    public void pauseApp() {

    }
    public void clear() throws IOException
    {
         b.destroy();
    }

    public void destroyApp(boolean unconditional) throws MIDletStateChangeException{
     
    notifyDestroyed();
    }

    public void commandAction(Command c, Displayable d) {
       if(c==Exit)
        {
         try {
                dos.writeUTF("eof");
             } catch (IOException ex) {
                  ex.printStackTrace();
                }
                notifyDestroyed();
         }

       if(c==Refresh){
            try {
                try {
                agent.startInquiry(DiscoveryAgent.GIAC, this);
                dialog1 = new Alert("Searching","Please Wait ,Searching devices",null,AlertType.INFO);
                dialog1.setTimeout(1000);
                Display.getDisplay(this).setCurrent(dialog1);
            } catch (BluetoothStateException e) {
                    throw new MIDletStateChangeException("Unable to start the inquiry");
}
            } catch (MIDletStateChangeException ex) {
                ex.printStackTrace();
            }
       }

       if(c==connect){
           Display.getDisplay(this).setCurrent(ChatForm);
         
           s= deviceList.getString(deviceList.getSelectedIndex());
           url =  "btspp://"+ s + ":" + "1" ;
           System.out.println(url);
           t.start();
       }
       if(c==send){
           sendmsg =  textfield.getString() ;
           textfield.setString("");
           this.ChatForm.append("\n"+"ME: "+sendmsg);
       try {
             dos.writeUTF(address+sendmsg);
           } catch (IOException ex) {
                ex.printStackTrace();
              }            
       }
 }

    public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
         try {
            String deviceaddress = btDevice.getBluetoothAddress();
            String address = btDevice.getFriendlyName(true);
            deviceList.insert(0, deviceaddress , null);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

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

    public void serviceSearchCompleted(int transID, int respCode) {
       
    }

    public void inquiryCompleted(int discType) {
        Alert dialog = null;
        if (discType != DiscoveryListener.INQUIRY_COMPLETED) {
            dialog = new Alert("Bluetooth Error","The inquiry failed to complete normally",null, AlertType.ERROR);
          }
         else {
              dialog = new Alert("Inquiry Completed","The inquiry completed normally", null,AlertType.INFO);
              }
              dialog.setTimeout(500);
              Display.getDisplay(this).setCurrent(dialog);
                                
    }

    public void run() {
        try {
               conn = (StreamConnection) Connector.open(url);        
               dos = conn.openDataOutputStream();     
            } catch (Exception ex) {
               System.out.println("here");
                ex.printStackTrace();
           }
        }
     public void setText(String s)
     {
        this.ChatForm.append("\n"+"Friend: "+s);
      }

    public void getChatForm()
    {
        textfield = new TextField("type text ","",50,TextField.ANY);
         exit = new Command ("Exit", Command.EXIT,1);
         send = new Command ("send",Command.OK,1);
         ChatForm.append(textfield);
         ChatForm.append("---------------------");
         ChatForm.addCommand(exit);
         ChatForm.addCommand(send);
         ChatForm.setCommandListener(this);
  }
    void setUp(String url1)
    {
       try{
        url =  "btspp://"+ url1 + ":" + "1" ;
        t.start();
       }catch(Exception e){
       e.printStackTrace();
       }
    }
}

-------------------------------------------------------------------------------------------------------------------


Server.java:-



import java.io.*;
import javax.bluetooth.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.Display;

/**
 * @author Vaibhav
 */
public class Server implements Runnable   {

    public DataInputStream dis;
    private StreamConnection con;
    public boolean listening = false;
    private Client Client;
    StreamConnectionNotifier notifier = null ;
    String msg,msg1,msg2;
    int count;
    public Server(Client Client)
    {
      this.Client = Client;
      count=0;
       try{
         Thread t = new Thread(this);
         t.start();
        }
       catch(Exception e)
        {}
   }
   public void run() {
          try {
    // retrieve the local Bluetooth device object
    LocalDevice localDevice = LocalDevice.getLocalDevice();
    // retrieve the Bluetooth address of the local device
    String address = localDevice.getBluetoothAddress();
    // retrieve the name of the local Bluetooth device
    String deviceName = localDevice.getFriendlyName();
    System.out.println(address+"   "+deviceName);
    DiscoveryAgent agent =localDevice.getDiscoveryAgent();
    localDevice.setDiscoverable(DiscoveryAgent.GIAC);
     UUID uuid = new UUID(0x0009);
    String url = "btspp://localhost:" + uuid + ";name=" + deviceName + ";" +
                  "authenticate=true"  ;
    notifier = (StreamConnectionNotifier) Connector.open(url);
    con =notifier.acceptAndOpen();
    dis =con.openDataInputStream();
    listening = true;
    setChat();
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
 }
   public  void  destroy() throws IOException
    {
     notifier.close();
    listening = false;
    }
   public void  setChat()
    {
     try{
         while(listening)
          {
            msg = dis.readUTF();
            msg1=msg.substring(0,12);
            msg2=msg.substring(12);
            if(count==0)
            {
            Client.setUp(msg1);
            }
            count=1;
             try{
                 if(!msg2.equals("eof")){
                    Display.getDisplay(Client).setCurrent(Client.ChatForm);
                    System.out.println(msg2);
                    Client.setText(msg2);
                   }
                    else
                     listening=false;
             }
              catch(Exception e)
                        {
                            e.printStackTrace();
                        }
              }
       }
            catch(Exception ex)
                      {
                          ex.printStackTrace();
                      }
       
    }
}

------------------------------------------------------------------------------------------------------------------

Now first we will go through the Midlet Client.java
As you can see ,it is almost similar to the previous tutorial code ,device discovery.
When constructor client runs ,it initialises the Displayable item.
StartApp()  meanwhile creates the instance of Server class and calls its constructor.
It also calls getChatForm() which defined the display of chatform as you can see in the getChatForm function code.
Rest of the command is same as it was in device discovery.

Now when refresh button is pressed, then the mobile searches for bletooth device through startInquiry(0 as explained in previous tutorial.
After we have got a list of devices and then we press connect on selected address then the commandaction of connect comes into play.
It checks for the selected device , gets its address and creates a URL as visible in following statements.

 s= deviceList.getString(deviceList.getSelectedIndex());
           url =  "btspp://"+ s + ":" + "1" ;

Then the Thread is started.

The run function is excecuted , in which
conn = (StreamConnection) Connector.open(url);        
               dos = conn.openDataOutputStream();
commands creates a stream connection to the url created in connect command.

Then a dataoutput stream is opened to send data.
Now when send command is given ,
sendmsg =  textfield.getString() ; gets the string entered.

This append the sent message to sender's screen.
this.ChatForm.append("\n"+"ME: "+sendmsg);

Then this command sends the data and address of the sending mobile through outputstreamconnection.
dos.writeUTF(address+sendmsg);
This concludes client side coding.


Now in server class,as soon as its instance is created by client ,its constructor runs.
this.Client = Client;
Above command hepls the class to locate its parent class.
Then it starts the thread.
The run function on server is executed.

This statement  retrieves the local Bluetooth device object
    LocalDevice localDevice = LocalDevice.getLocalDevice()
;
    Then it retrieve the Bluetooth address of the local device
    String address = localDevice.getBluetoothAddress();

    This retrieve the name of the local Bluetooth device
    String deviceName = localDevice.getFriendlyName();

    This creates a discoveryagent.
    DiscoveryAgent agent =localDevice.getDiscoveryAgent();


This sets the device as discoverable.Check for other options available for hiding the device.
    localDevice.setDiscoverable(DiscoveryAgent.GIAC);
     UUID uuid = new UUID(0x0009);
    String url = "btspp://localhost:" + uuid + ";name=" + deviceName + ";" +
                  "authenticate=true"  ;

above 2 statements prepares the Connection URL.
This statement creates the connection notifier.
notifier = (StreamConnectionNotifier) Connector.open(url);
Now the essence of our coding was that it didn't required approval .here is the piece of code which decides it.
con =notifier.acceptAndOpen();
It automatically accepts incoming connection and opens stream.
dis =con.openDataInputStream();
Then setchat function is executed.

msg = dis.readUTF();
            msg1=msg.substring(0,12);
            msg2=msg.substring(12);
Above coding is done to seperate address and the text so that address can be used to connect back to the sender and data is displayed on chatform (however setText function of client is  used for this purpose.)


However when count is 0 ,it calls setUp function. This is done when the reciever recieves data for the first time .This is done so that it can connect back to the sender to reply. However when reciever sends back 2nd time ,the count increses to more than 0 and it skips this part.
Finally setUp function of client just prepares the connection URL for server to connect back.

This concludes our tutorial .
In next tutorial we'll learn request/response connection in which reciever can accept /reject the connection.











No comments:

Post a Comment

customised by Vaibhav