Sunday, February 22, 2009

So basically the thing is, i want to send files to mobile devices without installing any software in mobile handset. So how can i do that? Obviously google.

You can send files to mobile device using OBEX, a file transfer protocol for bluetooth devices, it's in jsr82.

And there is a api known as bluecove which has things ready made :). Supported stack(don't ask me what it is, i know little about i) list can be found here. A list of jsr82 compatible handsets can be found here.

I work with netbeans, you can get the latest netbeans ide from here.

You will need the bluecove-api jar, and you can download from here. The jar i used was named "bluecove-2.1.0.jar", Now here is an issue, if you want your application to run in ubuntu/linux then you will also need a jar called "bluecove-gpl-2.1.0.jar" which can be found in here. So copy this jars to the netbeans project folder. And add these jar's in the project libraries, go to project properties and from libraries at left select add jar/folder and show the jars.


Now you are ready to use bluecove with your project. Do some coding things as you like.

Here I am going to make an application which will discover devices around it and send them a file.

I used real bluetooth devices and handset. There is also possible to use emulators to emulate bluetooth dongle and also mobile device. But I don't know how, you can let me know if you find a easy one.

Ok now coding time, the application has three main parts
1. UI which is shown to user
2. BluetoothBrowser: a class that discovers remote devices and put them in a list, and this class is also used to find the OBEX url for sending files to remote device.
3. A sender class which sends file to remotedevices using the OBEXUrl found previously.

Now, while starting to work first, i found some examples where connectionurl was hardcoded like
btgeop://address:9
But this was not working for me, this is a port number in remote device in which obex service is running, but this port number is not valid for all handsets. For nokia it works fine, but in Sony Ericsson the obex port number is 6, so to make the program independent a findObex function was used to query the remote device to know it's obex connection url and then it was used to send the file. So more generic way. This part almost made me to fail as I was not able to do while the port number was 9 with sony ericsson.

The other codes are there, you might find similarity with codes in the net. But what can i do , i am a google coder. So things are copy paste copy paste bla bla.

The application starts discovery first then tries to send a jpeg file from "C://a.jpg" file.

Enought talking, now the happy part, the Source Code :).
The full source can be found here. The code is not tested, i plugged my code from other projects and made a quick project. So if you find now working let me know.

By the way for linux things, you might have a look at here
For ubuntu 8.10 additional library is required, to install that library in terminal run this command
sudo apt-get install libbluetooth-dev

It will save your time, in ubuntu i was getting bluecove stack not found though my bluetooth device was there, just running the above command will solve the issue, And remember to include the bluecove-gpl-2.10.0 jar with your project. the gpl jar has to be with the same version of your main bluecove jar.

I think i am still not clear to you. what can i do i am bad at writing and explaining.

The next one i am wishing to write is "How you can receive contacts/vcard/business card" from mobile devices using obex.

35 Comments:

  1. Anonymous said...
    hi , nice article , this article helps a lot for beginners ,i tested ur code on windows xp , bluetooth devices will be discovered but while sending files it hangs.I get this message
    **********Now sending file to device **********
    null

    after that message it hangs
    Shimul said...
    It's not hanging in there
    though the null is printed but that has no relation

    This was a println which was in another code

    But in my pc it can send files to mobile handsets.

    I tested using k550

    Can you recheck?
    Anonymous said...
    hey , i rechecked it , but still not able to send files , this was the output i got when i run the program
    BlueCove version 2.1.0 on bluesoleil
    Starting inquiery
    device discovered
    refresh
    1
    finding obex
    trans id1
    sleeping
    in services discovered
    found service on W810i urlbtgoep://001A75631AEF:6;authenticate=false;encrypt=false;master=false
    in service search completed
    sleeping
    ***************Now sending file to device*****************
    null
    FILE SUCCESSFULLY NOT SENTa.jpg in exception
    java.io.IOException: Can't connect [General fail]
    at com.intel.bluetooth.BluetoothStackBlueSoleil.connectionRfOpenImpl(Native Method)
    at com.intel.bluetooth.BluetoothStackBlueSoleil.connectionRfOpenClientConnection(BluetoothStackBlueSoleil.java:368)
    error closing connectionjava.lang.NullPointerException
    at com.intel.bluetooth.BluetoothRFCommClientConnection.(init)(BluetoothRFCommClientConnection.java:37)
    at com.intel.bluetooth.MicroeditionConnector.openImpl(MicroeditionConnector.java:387)
    at com.intel.bluetooth.MicroeditionConnector.open(MicroeditionConnector.java:162)
    at javax.microedition.io.Connector.open(Connector.java:83)
    at com.nextigen.blue.SendFileTask.run(SendFileTask.java:81)
    at java.lang.Thread.run(Thread.java:619)

    i am using w810i phone , the phone can be discovered but not able to send files
    Shimul said...
    1. the file has to be in c drive and named a.jpg

    The error might be due to bluesoliel, bluesoliel is a bad thing

    If you are running under windows xp service pack 2, then uninstall bluesoleil and restart your pc and try to run the code again, then the bluetooth will work with the default bluetooth driver provided by microsoft.

    No problem with the set, i also worked with w810i before.
    Anonymous said...
    oh k , i will try it , thanks a lot for replying
    Anonymous said...
    i uninstalled bluesoleil and tried , now its working fine :)
    Shimul said...
    good to hear that, bluesoleil might have some issue, bluecove also says those
    Junita said...
    What is bluesoleil ?
    Junita said...
    This comment has been removed by the author.
    Shimul said...
    @alibi
    bluesoleil is a bluetooth access manager software
    It has driver to access bluetooth devices.
    You can see details in here

    http://www.bluesoleil.com/
    Anonymous said...
    Hi,very nice article,,I tried running the code ...it sends the message but the program doesnot end!!!!

    Also,how can I make it rerun automatically???


    Pleeeeeese could u answer me ASAP??
    Shimul said...
    you can rerun based on your requirement

    like in my other codes, i run the query of remote devices in a loop, so after each completion of a service discovery the application again calls the query function
    Shimul said...
    at the end of refreshList function if you add this line the query will run again and again
    browser = new BluetoothBrowser(this);
    or in the BlutoothBrowser class
    in the thread you can loop it
    Neuw said...
    Hi there, I tested your code in Linux (ubuntu 9.04) and works great. Thx
    Unknown said...
    Hi Shimul, thanks a lot for the code, but I would like to ask how can i directly send the a.jpg to a specific phone considering that i have the phone's BT address and ObexURL. What are the necessary portions that I would need to make it work?
    Shimul said...
    @Ryan
    You see the function named refreshlist, you can remove all the codes in here and call
    StartSendFileTask(device.getBluetoothAddress(), "C://a.jpg", obexURL);

    with the parameter of bluetooth address and obex url

    this will not stop the bluetooth inquery though

    But if you also don't want to inquiry for bluetooth devices just in this function

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
    // TODO add your handling code here:
    browser = new BluetoothBrowser(this);
    }

    remove the codes in the function and put the line in there

    StartSendFileTask(device.getBluetoothAddress(), "C://a.jpg", obexURL);

    So the new code will look like

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
    // TODO add your handling code here:
    StartSendFileTask(device.getBluetoothAddress(), "C://a.jpg", obexURL);

    }
    Unknown said...
    Wow thanks a lot Shimul, I got it to work perfectly by following your instructions :)

    However, I would like to refine the BlueMain by stripping down all the UI components and by far, I only managed to get only this:

    import java.io.File;
    import java.io.FileInputStream;
    import java.util.List;
    import javax.bluetooth.RemoteDevice;
    import javax.swing.DefaultListModel;

    public class BlueMain{
    public static void main(String args[]) {
    String deviceAddress="001E458436D5";
    String fileToSend="C://a.jpg";
    String obexURL="btgoep://001E458436D5:7;authenticate=false;encrypt=false;master=false";

    FileInputStream stream = new FileInputStream(fileToSend);
    File f = new File(fileToSend);
    int size = (int)f.length();
    byte file[] = new byte[size];
    stream.read(file);
    String filename = f.getName();
    System.out.println("***************Now sending file to device*****************");
    SendFileTask task = new SendFileTask(deviceAddress, file, filename, obexURL);
    Thread thread = new Thread(task);
    thread.start();
    }
    }
    I am getting compilation errors so I guess I must have messed up somewhere. Can you help me point out my mistakes? Thank you again Shimul.
    Unknown said...
    Hi Shimul,
    It was excellent article which gave me an elementary idea on bluetooth implementation. It was very useful.

    I have changed the UUID part also add attrset as below. Now it is working with all the mobiles like Nokia,Sonyeric,Windows mobile.

    UUID[] searchUuidSet = { new UUID("1105", true) };
    int[] attrSet = { 0x0100, 0x0003, 0x0004 };

    I need a code sample which will send a text message from PC to mobile via bluetooth ( i am using blue cove and bluesoleil in the PC ) despite sending files. Can any one of you pls help.

    Thanks
    Anand
    Piero said...
    Hey all,

    Thanks Shimul for this cool article, helps a lot!

    I am trying like Ryan to remove the user interface.

    After removing all the interface elements, I am trying to call the browser in BlueMain, it starts but doesnt actually do the enquiry:

    run:
    BlueCove version 2.1.0 on bluez
    Starting inquiry
    BlueCove stack shutdown completed
    BUILD SUCCESSFUL (total time: 0 seconds)

    I know its a bit off-topic, but do you know what modifications I have to do to get it to run only in the terminal and that it wont shutdown like that?

    Thx,
    P
    Shimul said...
    hi pierro,
    why don't you start the enquiry again when an enquiry is completed. Then the enquiry will be continued for infinity
    Piero said...
    Thanks for your answer.

    I managed it to work by just setting up
    BlueMain().setVisible(false);

    and calling the action usually started by clicking the button in the BlueMain constructor...
    so its not really a good solution but...

    Basically what I wanted to achieve is something like:

    java -jar "blue.jar" "fileNameToPush"

    which is working now.

    I am not sure what Im doing wrong, but when I strip the UI, I cannot get it to work properly... I havent been programming in Java for a while now... I feel like a noob again! :)

    Also, I cannot find where to put a System.exit() once the file has been pushed once to all the detected devices.
    Shimul said...
    hi piero,
    Looks like bluecove requires an UI application to work.

    So about exiting your application after sending what you can do is,

    the RefreshList is starting the threads to send files to remote devices. As we don't know when the threads will end so we cannot just call system.exit from this function.

    What we can do is keep count of number of threads started to send files, and from the each thread when files are sent they can acknowledge the main class that the file is sent.

    And in there if we see all files are sent then we can exit the application.

    So what I am telling is in SendFileTask, pass the reference of your mainclass. And after completing sending a file SendFileTask will call a specific function of mainclass. increase your counter there. And when the count is equal to the number of threads you started that means that all the threads have completed their task. So you can exit your app then. I hope i am clear

    Thanks
    Piero said...
    Yes its clear! Thats what I was thinking about...

    Also, since its possible to know how many devices have been detected, it should be quite easy!

    Thanks for your support and for sharing your knowledge :)
    Piero said...
    This comment has been removed by the author.
    Piero said...
    Hey Shimul,

    I am sorry to come back on to you one more time, but there is something I do not understand in this script.

    I cannot see where the serviceSearchCompleted method (in the Browser class) is called, although I can see in the execution that it is called...

    The problem is that this method is executed twice for the devices where the responseCode returns SERVICE_SEARCH_ERROR, and I dont understand why.

    I have been trying to count the started threads, to use thread locks etc, but I do not find a working solution...

    As a reminder, I am trying to have 2 versions of the script.
    One exiting once all the discovered devices have been searched and the file has been pushed to the reachable devices
    The second version will be alike, except that instead of exiting, it will just launch itself again.

    If you could help it would be greatly appreciated... if not well, I'll post a solution if ever I find one! :)
    Shimul said...
    ok pierro, here is the thing. First we do device search. Then we try to find the obex url of this device by doing another service search. And in the obex search there is two method it tries to find the obex url, in the BluetoothBrowser class you will find a method called findobex, here you will see the code is trying to do two service search if one fails. I think that might be causing such results. Can you check. I don't have the system ready in my pc so i am not able to test myself.
    Piero said...
    Yes I will check.

    I will be on holidays for the next two weeks, so I will get back to you when I come back...

    Also I am now trying to adapt this into a web application, basically a web page that sends files via bluetooth when a link is clicked... and I have many problems :p

    I will post again here soon...

    Regards,
    P
    Karthick Jeeva said...
    hi all,
    shimul good article.I got the basics of bluetooth fuctionality thanks.Can i use this code n modify it to send files from my mobile to pc and store it in pc.please help!
    Shimul said...
    @karunya

    Please refer to this post to receive file/contacts from mobile device


    http://getablogger.blogspot.com/2009/02/receive-business-cardvcardcontact-from.html

    thanks
    shimul
    Unknown said...
    Hey very nice blog,
    I had use file sending part of this code along with code given on jsr82.com and it works well..

    Thanks...
    Unknown said...
    Hey very nice blog,
    I had use file sending part of this code along with code given on jsr82.com and it works well..

    Thanks...
    MrCarneval said...
    Hi, thanks for the article. I have a question. Why do I get an exception when i reject receiving files?

    I mean, when i get message on my phone to accept file, i say "cancel", and then program shows me this exception:

    FILE SUCCESSFULLY NOT SENTa.jpg in exception
    javax.bluetooth.BluetoothConnectionException: Failed to connect; [10064] A socket operation failed because the destination host was down.
    error closing connectionjava.lang.NullPointerException
    at com.intel.bluetooth.BluetoothStackMicrosoft.connect(Native Method)
    at com.intel.bluetooth.BluetoothStackMicrosoft.access$700(BluetoothStackMicrosoft.java:44)
    at com.intel.bluetooth.BluetoothStackMicrosoft$ConnectThread.run(BluetoothStackMicrosoft.java:651)

    My question is, why this exception come out? And why is responseCode from obex is null, and not some other number?

    How can I know if user rejected receiving, and not bluetooth timed out? Because when a session times out I get the same exception.

    This is very important for me. Please help me.
    Thanks
    Unknown said...
    The files sent are received in mobile inbox. any way to send it to a folder in memory card.
    Anonymous said...
    It's not working for me, I'm using Windows Xp.
    t said...
    hello, i am not able to download the code
    could you please help me on this
    thank you

Post a Comment