Ok after several days of trying different solutions, I am now able to switch between the afore mentioned printers. Since I am not entirely sure which of my measures was the reason for succeeding, I'll list them all, so someone stumbling upon this post will have some clues on how to fix his bluetooth issues. One thing however I am quite sure about: You don't need different UUIDs to connect two different printers - you can use the same UUID (But I only ever have one of them switched on).
I cache the device that was last printed to - however unlike before I no longer cache the actual BluetoothDevice, instead I only cache it's mac address which is obtainable through:
BluetoothDevice bluetoothDevice;
//Obtain BluetoothDevice by looking through paired devices or starting discovery
bluetoothDevice.getAddress();
getAddress() returns a String: The hardware address of the device. I cache that mac address and next time the user wants to print, I match the cached mac address against the mac addresses of all paired printers - if the mac address matches one of these, I try to connect to that printer. If that fails, I reset my cached mac address and try to find another device by first checking my paired devices if one of them can connect (if I can successfully connect I update my cached mac address accordingly), and if that fails I start a bluetooth discovery looking for other potential devices.
Now in order to not leave any socket connections open to one of my printers my routine is as follows (I'll leave out the try-catches I have wrapped around each call to ease the read):
Create the socket
BluetoothSocket btSocket = btDevice.createRfcommSocketToServiceRecord(MY_UUID);
The MY_UUID refers to the well known UUID used for connecting to SPP devices:
00001101-0000-1000-8000-00805F9B34FB
If the socket creation fails (which is rare and if it happens it's most likely due to insufficient permissions or bluetooth being disabled/not available), we can't proceed further, as we need a socket to connect to. Hence, in your catch block you should trigger the disconnect method (more on that later).
Connect to the created socket
bSocket.connect();
If the connect fails, we can't proceed further, as we need a valid socket connection to obtain the input and output streams. Hence, in your catch block you should trigger the disconnect method (more on that later).
Obtain the input and output stream
The next step would be to obtain the input and output streams from the socket. I do this in a for loop which runs a couple of times (5 times should be enough) - in each iteration I check if I have the output stream, if not, I try to obtain it, same for the input stream. At the end of the loop I check if I have both my streams, if yes I exit the loop (AND the whole connect method), if no, I proceed with the loop and try again. Usually I get both my streams in the first loop-iteration, however sometimes I need two or three iterations to obtain both streams.
If I reach the code that follows after the loop declaration I obviously did not get my streams or something else went wrong. At this point the connect is considered to have failed and I execute my disconnect code (which cleans up open streams & sockets, more on that later).
Read/Write
Now that you have a connection to your target bluetooth device you can perform read and write operations. Once you're done you should cleanup by closing all streams and sockets, more on this in the next paragraph: Disconnecting. Remember: If an exception occurs during read/write operations, be sure to trigger the disconnect method in order to cleanup your resources. If your printer needs some kind of initialization command, be sure to send that right after connecting to the printer and before performing your read/write operations.
Disconnecting
There are usually two occasions on which you should disconnect:
- Once you're done with your read/write operations
- If an exception occurred somewhere along the way, to cleanup your resources
Close your streams
The first thing you want to do is cleanup your streams, check both, your input and output stream, if they're not null, close them and set them to null. Be sure to wrap each operation (closing the input stream, closing the output stream etc...) into its own try-catch as otherwise failing to do one cleanup (Because an exception is raised) will skip all other cleanup measures.
Close the socket
Now that you've made sure your input streams are cleaned up, proceed to closing your socket connection and setting it to null thereafter.
One more thing: I have a Thread.sleep at the beginning and end of my disconnect method. The one in the beginning is about 2.5 seconds (= 2500 milliseconds) long, the purpose is to make sure nothing else is going on with the printer (such as pending read/write operations or the printer still printing etc..). The second Thread.sleep is at the end of my disconnect method and is about 800 milliseconds long. The reason for that sleep at the end is related to the problems I had when trying to immediately open a new socket right after closing one. For more details please refer to this answer.
Questions?
In case anyone has questions related to my OP or my answer, please let me know in the comments and I'll try my best to answer them.