Bluetooth

Three ways to send data over bluetooth with android

My recent app that I am developing involves bluetooth and I had to do quite some research about the whole thing and the android API. I had to do lots of searching, but in the end it was ok.
Anyway, while I was searching I had to scrape bits and pieces from every corner of the internet and put them together, so I decided I’ll make one general post about ways to send data over bluetooth in android. I’ll explain everything as we go.


Let’s start from the easiest one:

Intent intent = new Intent();  
intent.setAction(Intent.ACTION_SEND);   
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File("somefile.mp3")));
startActivity(intent);

This is a more intuitive way than the rest 3 but you has the least control with it. What this does is prompt the user which application to use to open the file with – it displays a list. Of course the user selects Bluetooth and then it displays bluetooth settings where the user picks out the device and the transfer is initiated. Needless to say it uses in-built services.
Good for simple things, but isn’t very professional. Also you cannot send any file type you want because of the MIME types.

A bit more complicated is the next snippet:

ContentValues values = new ContentValues();
String address = device.getAddress();
values.put(BluetoothShare.URI, Uri.fromFile(new File("somefile.mp3")).toString());
values.put(BluetoothShare.DESTINATION, address);
values.put(BluetoothShare.DIRECTION, BluetoothShare.DIRECTION_OUTBOUND);
Long ts = System.currentTimeMillis();
values.put(BluetoothShare.TIMESTAMP, ts);
Uri contentUri = getContentResolver().insert(BluetoothShare.CONTENT_URI, values);

To use this snippet, you will need this class. Save it as BluetoothShare.java.
Now this snippet is a bit more professional. It still uses the in-built bluetooth service and I heard it doesn’t work on many devices, but no one has confirmed that.
This snippet doesn’t prompt the user for action, instead it sends the data to a ContentResolver then it gets re-routed to the Bluetooth service and put into the stack. From there the file transfer is programatically initiated.
It’s good for sending a file, but you don’t have much control over the process – you cannot programatically cancel the transfer, you cannot empty the stack, you cannot receive feedback through callbacks… Once the last line is executed you don’t have control any more.
Still for file transfer it’s the best solution and you can send any kind of file you want, as long as the receiver accepts it.

Last snippet is the hardest:

public void sendFile(Uri uri, BluetoothSocket bs) throws IOException {
	BufferedInputStream bis = new BufferedInputStream(getContentResolver().openInputStream(uri));
	OutputStream os = bs.getOutputStream();
    try {
        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];
 
        // we need to know how may bytes were read to write them to the byteBuffer
        int len = 0;
        while ((len = bis.read(buffer)) != -1) {
            os.write(buffer, 0, len);
        }
    } finally {
    	bis.close();
        os.flush();
        os.close();
        bs.close();
    }
}

Needless to say that this only works if you have the Client-Server architecture on both your devices.
To use this, you need to initiate a connection to the device and call this method passing the file URI and active socket as a parameter. It converts the file in chunks and writes them to the stream.

Looks simple, but it is completely different from the first two snippets because it uses the socket to send and receive data which establishes the RFCOMM channel. In-built services use an OBEX OPP mode which have its own packets and headers. You can read more on OBEX PUSH profile in this document (specifically what kind of headers must be included are defined on page 21).

Subscribe
Notify of
guest

20 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments