I am building tic tac to for two players and need a Bluetooth connection to exchange some data, I can enable Bluetooth, enable discover-ability but my problem in "BluetoothServerSocket" and the client "BluetoothSocket", I don't know how to manipulate this part,
this is the code:
ArrayList<String>al=new ArrayList<String>();
BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = ba.getBondedDevices();
if(pairedDevices.size()>0)
for(BluetoothDevice d: pairedDevices)
al.add(d.getName()+" , "+d.getAddress());
if (!ba.isEnabled())
ba.enable();
BluetoothDevice device;
Intent dis=new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
dis.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);
startActivity(dis);
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(UUID);
socket.connect();
InputStream is=socket.getInputStream();
OutputStream os=socket.getOutputStream();
Both the players will communicate over 'BluetoothSocket's using which you can send/receive data using InputStreams and OutputStreams. But for getting such a pair of sockets you can do this thing :
Create BluetoothServerSocket on the side of one player and other one connects to it. The BluetoothServerSocket listens for connections using the 'accept' method which blocks till a client BluetoothSocket connects to it. After that the BluetoothServerSocket.accept() method returns a BluetoothSocket which can be used with the client Btsocket for 2-way info transfer.
Hope this helps...
PS: createRfcommSocketToServiceRecord just creates one such client mentioned above. You may use the same UUID for both sides
It seems you're missing a lot of complexity regarding data exchange. Mainly you'll need to deal with threads to listen/send data. Here you have a complete implementation of what I'm talking about: https://github.com/buddles/AndBT/blob/master/AndBT/src/br/pucrs/tcii/BluetoothService.java
Have you considered to use an already implemented library? This project comes with a TicTacToe sample and a Chat app that supports up to seven connections: https://github.com/buddles/AndBT
You may refer this link. This is a simple bluetooth chat app. You can modify this app to send and receive the required data.
Related
I have a working Bluetooth server running (Android app). I would like to set a specific Bluetooth port for it to listen to. The reason for that is that for the client to connect, it takes about 10-15 seconds because it needs to first discover the server (i do a scan ).
the code to create the server is the following:
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
UUID my_uuid = UUID.fromString("12345678-f6ff-4f6f-1f1f-f8f8f8fffff8");
try {
BluetoothServerSocket serverSocket = adapter.listenUsingRfcommWithServiceRecord("myBluetoothServer", my_uuid);
sock1 = serverSocket.accept();
i_s = sock1.getInputStream();
o_s = new OutputStreamWriter(socket.getOutputStream());
new Thread(writter).start();
...
Question: how to specify a fixed port number for the server?
I have been looking here, of course, but it is not easy to find,:
https://developer.android.com/reference/android/bluetooth/BluetoothSocket?hl=ur
I am looking for something like serverSocket.setPort(myPortNumber) (pseudo - code)
The concept of port does not exist for Bluetooth Sockets since they are not regular TCP/IP sockets. They are just abstracted to behave like one.
As you figured out from your code, what you specify is a UUID which is a service identifier. The process to connect to a Bluetooth server goes like this:
Bluetooth Device scan: You can't skip this part, since you need a valid BluetoothDevice object
Service Discovery for a discovered Device: This is the part where you "check" if that Bluetooth Device is running the service that you are looking for (Your service UUID) So you shouldn't skip this part either, unless you want to connect to all surrounding Bluetooth devices.
I want to receive images via Bluetooth and display that image in Image View.I know how to pass image from one activity to another activity but i don't no how to receive images using Bluetooth.
Android framework provides access to the Bluetooth functionality through the Android Bluetooth APIs. These APIs let applications wirelessly connect to other Bluetooth devices, enabling point-to-point and multipoint wireless features.
Using the Bluetooth APIs, an Android application can perform the following:
Scan for other Bluetooth devices
Query the local Bluetooth adapter for paired Bluetooth devices
Establish RFCOMM channels
Connect to other devices through service discovery
Transfer data to and from other devices
Manage multiple connections
Create a BluetoothSocket and connect to it:
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(<your-device>.getUuids()[0].getUuid());
socket.connect();
Listen to the socket (Get data from the device)
InputStream inStream = socket.getInputStream();
while (inStream.available() > 0) {
inStream.read(); // <-- data from device
}
Write to the socket (Send data to the device)
OutputStream outStream = socket.getOutputStream();
byte[] bytes = <some-data>
outStream.write(bytes);
and for more details you can read Bluetooth Api Documentation here
My understanding is that the SDP is a list of UUIDs that other devices can fetch.
According to this PDF from MIT, "A more general way to think of
SDP is as an information database." Does this mean I can add multiple values to SDP? Since Android has BluetoothDevice.fetchUuidsWithSdp(), how do I set the UUIDs of a device?
Also, what does each section of an UUID mean? UUIDs look like 00000000-0000-1000-8000-00805F9B34FB, but what information does this convey?
An UUID identifies a service that is available on a particular device. So if you call BluetoothDevice.fetchUUidsWithSdp() your BroadcastReceiver will receive the relevant Intent ACTION_UUID containing the device and the service UUID.
The bluetooth specification defines some common UUIDs.
If you don't want to connect to one of these well known services but intent to implement your own bluetooth application, then you have to just generate your own UUID (use uuidgen from a unix console or an online generator) that identifies your application/service.
You can create an UUID instance in java like this UUID uuid = UUID.fromString("785da8ea-1220-11e5-9493-1697f925ec7b");.
So if you create the server side for your bluetooth application on Android you typically do this
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
BluetoothServerSocket serverSocket = adapter.listenUsingRfcommWithServiceRecord("YourHumanReadableServiceName", uuid);
And this is where you "set" your UUID. The Android bluetooth API creates the SDP-entry consisting of YOUR application's UUID and name for you. Other devices can now retrieve this entry. Androids bluetooth stack will now associate a bluetooth channel to your BluetoothServerSocket. If you want to connect to this ServerSocket, the connecting side usually connects doing this:
// you will most likely already have this instance from a discovery or paired device list
BluetoothDevice serverDevice = adapter.getRemoteDevice(bluetoothMacAddress);
// connect to your ServerSocket using the uuid
BluetoothSocket socket = serverDevice.createRfcommSocketToServiceRecord(uuid);
socket.connect();
Android will again do the heavy lifting for you: It checks the SDP-Records on the remote device, looks up the bluetooth channel that corresponds to your service's UUID and connects using this information.
There is a common code snippet spooking around here on SO that advices you to use "reflection" to get to a hidden API looking similar to this code:
try {
// this is the way to go
socket = device.createRfcommSocketToServiceRecord(uuid);
socket.connect( );
} catch ( IOException exception ) {
// don't do that! You will bypass SDP and things will go sideways.
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
socket = (BluetoothSocket) m.invoke(device, 1);
socket.connect();
}
Most people try this and it "just works" in their dev environment but you should know what you do using this. You actively bypass the SDP lookup that retrieves the right bluetooth channel to be used with your service and you will end up connecting to channel 1. If you have more than one Service running on the device, things WILL go sideways in this cases and you will end up in debugging hell ;-)
I developed a small middleware called Blaubot to create small networks using bluetooth/wifi/nfc and experienced all sorts of problems on the devices I used to test with (12 models). It was often the case that the bluetooth stack was not fully functional anymore in cases where it got some load or after many connects/disconnects (which you usually will have, if you are developing your app). In these cases the device.createRfcommSocketToServiceRecord(uuid) would occasionally fail and only turning the bluetooth adapter off and on again helped to bring the bluetooth adapters back to life (in some cases only after a full power cycle). If this happens and you use the reflection method, you will probably not have much fun with bluetooth.
But if you know this and keep concurrent calls to the BluetoothAdapter within bounds, bluetooth connections and the adapters will be pretty stable.
I am getting bluetooth socket connection problem and so tried various alternatives to connect.
It is like if first fails then second and if second also fails then third and so the main UI blocks during the process.
The exceptions are like -
"Service discovery failed" OR "Host is down"
My all three alternatives -
1) Connect with a connect() function
m = bdDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
socket = (BluetoothSocket) m.invoke(bdDevice, Integer.valueOf(i));
mBluetoothAdapter.cancelDiscovery();
socket.connect();
2) Connect with a accept() function
m = bdDevice.getClass().getMethod ("listenUsingRfcommOn", new Class [] {int.class});
BluetoothServerSocket returnValue =
(BluetoothServerSocket) m.invoke(bdDevice, new Object [] {29});
socket = returnValue.accept();
3) Connect with a well know SPP UUID
private final UUID my_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
socket = bdDevice.createInsecureRfcommSocketToServiceRecord(my_UUID);
mBluetoothAdapter.cancelDiscovery();
socket.connect();
The second alternative is recently added and so I am not sure that how is it different from first and third one. All will block the UI until connect, all can through IOException.
1) You are connecting as a client to your SPP device. Therefore your device must be expecting a connection before you can actually connect.
2) You are accepting the connection as the server. Your bluetooth device will be responsible for firing the connection requests.
3) You are connecting to a device that uses a particular UUID as it's Serial Port Profile (SPP). Think of this as similar to ports in http protocol. The 00001101-0000-1000-8000-00805F9B34FB, is one of the most common ones. More info : https://developer.bluetooth.org/TechnologyOverview/Pages/SPP.aspx
Additionally, if you are thinking on supporting multiple OS / handset versions. You might see those error messages after an initial broken comm. Android's bluetooth stack (bluez) was totally replaced on 4.2, but you might need to still handle previous known bugs.
Reflection in this case is a good thing (some parts of the bluetooth API wasn't public in older versions). But, in my experience, API level < 17; using createInsecureRfcommSocket instead of createRfcommSocket is much more reliable.
Hope this helps. But if you are building an app for a custom bluetooth spp device of yours, explaining how that devices handles comms could help pointing out the exact root of your problem. Although, bluetooth on Android is never straight forward.
I am developing an application which should connect 2 Android devices through Bluetooth automatically. Let's say they are already paired. Is it possible to achieve that?
Of course it is possible. I'll make a short tutorial out of the documentation:
Start with the BluetoothAdapter - it is your Bluetooth manager.
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
If bluetoothAdapter is null, it means that this Android device does not support Bluetooth (It has no Bluetooth radio. Though I think it's rare to encounter these devices...)
Next, make sure Bluetooth is on:
if (!bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, request_code_for_enabling_bt);
}
If it's not on, we start the activity which asks the user to enable it.
Let's say the user did enable (I guess you should check if he did, do it in your onActivityResult method). We can query for the paired devices:
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
Then loop over them: for(BluetoothDevice device : pairedDevices) and find the one you want to connect to.
Once you have found a device, create a socket to connect it:
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(YOUR_UUID);
YOUR_UUID is a UUID object containing a special ID of your app. Read about it here.
Now, attempt to connect (The device you are trying to connect to must have a socket created with the same UUID on listening mode):
socket.connect();
connect() blocks your thread until a connection is established, or an error occurs - an exception will be thrown in this case. So you should call connect on a separate thread.
And there! You are connected to another device. Now get the input and output streams:
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
and you can begin sending/receiving data. Keep in mind that both actions (sending and receiving) are blocking so you should call these from separate threads.
Read more about this, and find out how to create the server (Here we've created a client) in the Bluetooth documentation.