I am trying to send plain text via Bluetooth, but it is converted to HTML somewhere.
The code I'm using is basically this:
String content = "This is just a test";
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, content);
sendIntent.setType("text/plain");
String title = "Share with…";
startActivity(Intent.createChooser(sendIntent, title));
When I run this code and choose the Bluetooth option, the file is pushed to the remote system with the name "bluetooth_content_share.html" and with these contents:
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/></head><body>This is just a test</body></html>
I've tried calling setType
before adding the EXTRA_TEXT
with no change in symptoms. Other share actions ("Add to Dropbox", for example) get the data as plain text. And I have been able to use other applications ("ES File Explorer", for example) to successfully send plain text files via Bluetooth.
How can I get the data to be sent as just plain text like I asked?
I couldn't sleep so I decided to take a look at stackoverflow to see if there was anything interesting in the android tag. This question seemed simple enough, yet it proved very interesting since as you noted in the question it just creates a damn html file with the string as the content.
I assumed that bluetooth communication wanted to work with files and that Android was inferring that our text was html even though you clearly stated plain text.
The solution I came up with is basically forcing the app to share a text file as opossed to sharing the test
String
. I've been able to test this and your code too, and I was able to replicate the magical creation of the html file. This should help you.Update Due to the op concerns about leaving a file in the storage, and not being able to use a temporary file, I've updated the code to add a
FileObserver
to the file which allows us to monitor when a file is being modified and what type of action it's experiencing. In this case, all we need to monitor is theFileObserver.CLOSE_NOWRITE
action which will be triggered only when the file is being accessed to send it, and after it has finished working on it. Eliminating the file after it.If anybody is wondering why we are setting the
FileObserver
that far down the code, is to avoid it being triggered upon the creation and edition of the file itself. Since we added after the file has been written to, we will only be triggering the events that are required for sending it by bluetooth (in this case).TL;DR: You either have to create a file or implement a ContentProvider and send it as
EXTRA_STREAM
, but this breaks other apps that want to receive the data as text viaEXTRA_TEXT
. It's possible to implement an exception for the "Bluetooth Share" app by usingEXTRA_REPLACEMENT_EXTRAS
.I was able to find this code in the source for the Android Bluetooth app (com/android/bluetooth/opp/BluetoothOppLauncherActivity.java):
So if there's
EXTRA_TEXT
and noEXTRA_STREAM
, then send it tocreatFileForSharedContent()
, which, in turn contains this:In other words, the Bluetooth app explicitly converts anything sent as text to HTML. Thanks, Android!
The only two things that the Bluetooth app will accept as an
EXTRA_STREAM
are content: and file: URIs (com/android/bluetooth/opp/BluetoothOppSendFileInfo.java):So trying to send a data: URI doesn't work.
This means you either have to create a file or implement a ContentProvider. Just to send some damned plain text!
But this has the potential to break sharing with other apps that want to receive the data via the
EXTRA_TEXT
method. Fortunately, it's possible to create anEXTRA_STREAM
that is only provided to the Bluetooth Share app by usingEXTRA_REPLACEMENT_EXTRAS
:You still have to handle deleting the file, though, which becomes more complicated when the user chooses something other than Bluetooth to share with, since the file will never be opened, making the
FileObserver
solution in Juan's answer become incomplete.