Three ways to send data over bluetooth with android

Bluetooth

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).

guest
20 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
germanDeveloper
germanDeveloper
7 years ago

Hello,

I just read your blog entry and got a question:
Is there a way of establishing a bluetooth connection to transfer files with only the remote MAC address? My problem is that my application should only be installed on one side and also don’t want to use the built-in bluetooth app.

I would really appreciate to get a solution because I have been searching for several weeks without getting a solution.

Thanks,

germanDeveloper

mukesh
mukesh
7 years ago

hi….
i m trying a bluetooth chat app but can’t a find a proper code to send or receive strings. can get some hep here

James
James
6 years ago

does the 2nd method still work in current versions of android? i.e. 4.4.2?

Diego
Diego
5 years ago

Great post! How can I transfer more than one file?

Uri.fromFile(new File(“somefile.mp3”)));

Example: I have a folder “photosCam” and I want to transfer all pictures.

Diego
Diego
5 years ago

Thanks for your reply! I have another problem now! I need to delete all the pictures after the transfer. This is my code:

private void blTRansfer() {
    String origen = Environment.getExternalStorageDirectory().getAbsolutePath() + "/fotosComodin/";
    File directorio = new File(origen);
    File[] archivos = directorio.listFiles(); 
    try { 
        for(File file:archivos) 
        { 
        String	nombredearchivo = origen + file.getName();
            add_multiSelect_file(nombredearchivo);
 
            //
        }
 
        ArrayList uris = new ArrayList();
        int length = mMultiSelectData.size();
        Intent i = new Intent();
        i.setAction(android.content.Intent.ACTION_SEND_MULTIPLE);
        i.setType("image/*");
        for(int a = 0; a < length; a++) {
            File file = new File(mMultiSelectData.get(a));
            uris.add(Uri.fromFile(file));
 
        }
        i.setComponent(
                new ComponentName("com.android.bluetooth",                         
       "com.android.bluetooth.opp.BluetoothOppLauncherActivity"));
            i.putExtra(Intent.EXTRA_STREAM, uris);
            startActivity(i);
 
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Diego
Diego
5 years ago

I am new in android , Iwould appreciate if you help me changing my code , the method I throw by a button. I want to delete the full directory after the transfer. I try this “directorio.delete();” After the block of “try catch” and don’t delete the directory…

MM
MM
5 years ago

The second code seems ok as it deal with all types of file..
Can i get the complete code to how can i implement this thing in an app..??
Reply asap..PLZ..

MW
MW
5 years ago

Hello, I’m trying to implement the third way in your guide here. I have a server set up on a raspberry pi and a client set up on an android application and I want to send a video file from the raspberry pi to the android app and play the video on the application. So from what I understand, the third code segment you have here is to be executed on the server side (since that’s the one sending the file), however do you have any insight for the client side code or can you point me in the right direction? I’m having trouble finding it on google.

At this point, once the server executes the third code segment, the entire file should be present on the output stream, now it’s just a matter of taking that data from the stream and saving it somewhere on the app and then playing the video file right?

jm latour
jm latour
4 months ago

Hello.
I’m very interrested with your 2nd snippet.it is what i’m looking for for hours…

but you said “To use this snippet, you will need this class” and the link is broken…is there a way to get this class to make the snippet works ?

thanks

jm latour
jm latour
3 months ago

Thank you.
i tried it but i didn’t succed to make it works:
i have error:

Caused by: java.lang.SecurityException: Permission Denial: writing com.android.bluetooth.opp.BluetoothOppProvider uri content://com.android.bluetooth.opp/btopp from pid=17103, uid=10411 requires android.permission.ACCESS_BLUETOOTH_SHARE, or grantUriPermission()
even if i have in manifest

Last edited 3 months ago by Kulverstukas