how to send data (a string) to a paired device in android?
I am working on bluetooth for the first time. I got the list of paired devices. Now my requirement is I need to send some data (a string) to the device. how can I do that? I tried searching but didn’t find anything useful. Could anyone help out this?
The Android developer website provides some excellent documentation & sample code to help you do just that. developer.android.com/guide/topics/connectivity/bluetooth.html Hope that helps!
1 Answer 1
Something like this might suffice:
DataOutputStream os; BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter(); BroadcastReceiver discoveryResult = new BroadcastReceiver() < public void onReceive(Context context, Intent intent) < String remoteDeviceName = intent.getStringExtra(BluetoothDevice.EXTRA_NAME); BluetoothDevice remoteDevice; remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Toast.makeText(getApplicationContext(), "Discovered: " + remoteDeviceName + " address " + remoteDevice.getAddress(), Toast.LENGTH_SHORT).show(); try< BluetoothDevice device = bluetooth.getRemoteDevice(remoteDevice.getAddress()); Method m = device.getClass().getMethod("createRfcommSocket", new Class[] ); BluetoothSocket clientSocket = (BluetoothSocket) m.invoke(device, 1); clientSocket.connect(); os = new DataOutputStream(clientSocket.getOutputStream()); new clientSock().start(); > catch (Exception e) < e.printStackTrace(); Log.e("BLUETOOTH", e.getMessage()); >> >; registerReceiver(discoveryResult, new IntentFilter(BluetoothDevice.ACTION_FOUND)); bluetooth.enable(); if (!bluetooth.isDiscovering()) < bluetooth.startDiscovery(); >public class clientSock extends Thread < public void run () < try < os.writeBytes("anything you want"); // anything you want os.flush(); >catch (Exception e1) < e1.printStackTrace(); return; >> >
You will also need a lot of imports such as these:
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Method; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.util.List; import java.util.UUID; import android.os.Bundle; import android.os.StrictMode; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.util.Log; import android.view.Menu; import android.widget.Toast;
note that not all imports are necessary for this example code, your IDE might help you to sort them out for you.
Pass data on the os.writeBytes(«anything you want»); // anything you want line.
Bluetooth data transfer between two Android devices
I have been following this Android guide for Bluetooth communication To explain exactly what I want to do, when the two devices are paired, two different activities open up on each device (server and client) where on the server activity I have different buttons, and on the client activity there is just a textview. I want to be able to press a button on the server device and display it on the client. I have managed to establish a connection between the two devices, but now I want to send data which I have not been able to do. They give this code for data transfer:
private class ConnectedThread extends Thread < private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket) < mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the input and output streams, using temp objects because // member streams are final try < tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); >catch (IOException e) < >mmInStream = tmpIn; mmOutStream = tmpOut; > public void run() < byte[] buffer = new byte[1024]; // buffer store for the stream int bytes; // bytes returned from read() // Keep listening to the InputStream until an exception occurs while (true) < try < // Read from the InputStream bytes = mmInStream.read(buffer); // Send the obtained bytes to the UI activity mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer) .sendToTarget(); >catch (IOException e) < break; >> > /* Call this from the main activity to send data to the remote device */ public void write(byte[] bytes) < try < mmOutStream.write(bytes); >catch (IOException e) < >> /* Call this from the main activity to shutdown the connection */ public void cancel() < try < mmSocket.close(); >catch (IOException e) < >> >
// Send the obtained bytes to the UI activity mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
And is not explained in the guide. I don’t know what the mHandler is or does. Apart from the error, I don’t even really understand where to put this code. Should it be in the second activities (server and client) that I open or in the main? If in the Server activity, should it be in the onClick method for all the buttons with a different byte code to send for each button? And in this code, how do we distinguish who is sending and who is receiving?
Android sample bluetooth code to send a simple string via bluetooth
I want to send a simple string data such as ‘a’ from an android device to other one via bluetooth. I looked sample bluetooth code in android sdk but it is so complex for me. I cannot understand how I can send only specific data when I press a button. How can I solve this problem?
2 Answers 2
private OutputStream outputStream; private InputStream inStream; private void init() throws IOException < BluetoothAdapter blueAdapter = BluetoothAdapter.getDefaultAdapter(); if (blueAdapter != null) < if (blueAdapter.isEnabled()) < SetbondedDevices = blueAdapter.getBondedDevices(); if(bondedDevices.size() > 0) < Object[] devices = (Object []) bondedDevices.toArray(); BluetoothDevice device = (BluetoothDevice) devices[position]; ParcelUuid[] uuids = device.getUuids(); BluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuids[0].getUuid()); socket.connect(); outputStream = socket.getOutputStream(); inStream = socket.getInputStream(); >Log.e("error", "No appropriate paired devices."); > else < Log.e("error", "Bluetooth is disabled."); >> > public void write(String s) throws IOException < outputStream.write(s.getBytes()); >public void run() < final int BUFFER_SIZE = 1024; byte[] buffer = new byte[BUFFER_SIZE]; int bytes = 0; int b = BUFFER_SIZE; while (true) < try < bytes = inStream.read(buffer, bytes, BUFFER_SIZE - bytes); >catch (IOException e) < e.printStackTrace(); >> >
i get: java.io.IOException: read failed, socket might closed or timeout, read ret: -1 although I am not even calling run(). I am only calling init() and write()
I made the following code so that even beginners can understand. Just copy the code and read comments. Note that message to be send is declared as a global variable which you can change just before sending the message. General changes can be done in Handler function.
import android.annotation.SuppressLint; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Set; import java.util.UUID; public class multiplayerConnect extends AppCompatActivity < public static final int REQUEST_ENABLE_BT=1; ListView lv_paired_devices; Setset_pairedDevices; ArrayAdapter adapter_paired_devices; BluetoothAdapter bluetoothAdapter; public static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); public static final int MESSAGE_READ=0; public static final int MESSAGE_WRITE=1; public static final int CONNECTING=2; public static final int CONNECTED=3; public static final int NO_SOCKET_FOUND=4; String bluetooth_message="00"; @SuppressLint("HandlerLeak") Handler mHandler=new Handler() < @Override public void handleMessage(Message msg_type) < super.handleMessage(msg_type); switch (msg_type.what)< case MESSAGE_READ: byte[] readbuf=(byte[])msg_type.obj; String string_recieved=new String(readbuf); //do some task based on recieved string break; case MESSAGE_WRITE: if(msg_type.obj!=null)< ConnectedThread connectedThread=new ConnectedThread((BluetoothSocket)msg_type.obj); connectedThread.write(bluetooth_message.getBytes()); >break; case CONNECTED: Toast.makeText(getApplicationContext(),"Connected",Toast.LENGTH_SHORT).show(); break; case CONNECTING: Toast.makeText(getApplicationContext(),"Connecting. ",Toast.LENGTH_SHORT).show(); break; case NO_SOCKET_FOUND: Toast.makeText(getApplicationContext(),"No socket found",Toast.LENGTH_SHORT).show(); break; > > >; @Override protected void onCreate(@Nullable Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.multiplayer_bluetooth); initialize_layout(); initialize_bluetooth(); start_accepting_connection(); initialize_clicks(); >public void start_accepting_connection() < //call this on button click as suited by you AcceptThread acceptThread = new AcceptThread(); acceptThread.start(); Toast.makeText(getApplicationContext(),"accepting",Toast.LENGTH_SHORT).show(); >public void initialize_clicks() < lv_paired_devices.setOnItemClickListener(new AdapterView.OnItemClickListener() < @Override public void onItemClick(AdapterViewparent, View view, int position, long id) < Object[] objects = set_pairedDevices.toArray(); BluetoothDevice device = (BluetoothDevice) objects[position]; ConnectThread connectThread = new ConnectThread(device); connectThread.start(); Toast.makeText(getApplicationContext(),"device choosen "+device.getName(),Toast.LENGTH_SHORT).show(); >>); > public void initialize_layout() < lv_paired_devices = (ListView)findViewById(R.id.lv_paired_devices); adapter_paired_devices = new ArrayAdapter(getApplicationContext(),R.layout.support_simple_spinner_dropdown_item); lv_paired_devices.setAdapter(adapter_paired_devices); >public void initialize_bluetooth() < bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) < // Device doesn't support Bluetooth Toast.makeText(getApplicationContext(),"Your Device doesn't support bluetooth. you can play as Single player",Toast.LENGTH_SHORT).show(); finish(); >//Add these permisions before // // // // if (!bluetoothAdapter.isEnabled()) < Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); >else < set_pairedDevices = bluetoothAdapter.getBondedDevices(); if (set_pairedDevices.size() >0) < for (BluetoothDevice device : set_pairedDevices) < String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address adapter_paired_devices.add(device.getName() + "\n" + device.getAddress()); >> > > public class AcceptThread extends Thread < private final BluetoothServerSocket serverSocket; public AcceptThread() < BluetoothServerSocket tmp = null; try < // MY_UUID is the app's UUID string, also used by the client code tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord("NAME",MY_UUID); >catch (IOException e) < >serverSocket = tmp; > public void run() < BluetoothSocket socket = null; // Keep listening until exception occurs or a socket is returned while (true) < try < socket = serverSocket.accept(); >catch (IOException e) < break; >// If a connection was accepted if (socket != null) < // Do work to manage the connection (in a separate thread) mHandler.obtainMessage(CONNECTED).sendToTarget(); >> > > private class ConnectThread extends Thread < private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) < // Use a temporary object that is later assigned to mmSocket, // because mmSocket is final BluetoothSocket tmp = null; mmDevice = device; // Get a BluetoothSocket to connect with the given BluetoothDevice try < // MY_UUID is the app's UUID string, also used by the server code tmp = device.createRfcommSocketToServiceRecord(MY_UUID); >catch (IOException e) < >mmSocket = tmp; > public void run() < // Cancel discovery because it will slow down the connection bluetoothAdapter.cancelDiscovery(); try < // Connect the device through the socket. This will block // until it succeeds or throws an exception mHandler.obtainMessage(CONNECTING).sendToTarget(); mmSocket.connect(); >catch (IOException connectException) < // Unable to connect; close the socket and get out try < mmSocket.close(); >catch (IOException closeException) < >return; > // Do work to manage the connection (in a separate thread) // bluetooth_message = "Initial message" // mHandler.obtainMessage(MESSAGE_WRITE,mmSocket).sendToTarget(); > /** Will cancel an in-progress connection, and close the socket */ public void cancel() < try < mmSocket.close(); >catch (IOException e) < >> > private class ConnectedThread extends Thread < private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket) < mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the input and output streams, using temp objects because // member streams are final try < tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); >catch (IOException e) < >mmInStream = tmpIn; mmOutStream = tmpOut; > public void run() < byte[] buffer = new byte[2]; // buffer store for the stream int bytes; // bytes returned from read() // Keep listening to the InputStream until an exception occurs while (true) < try < // Read from the InputStream bytes = mmInStream.read(buffer); // Send the obtained bytes to the UI activity mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget(); >catch (IOException e) < break; >> > /* Call this from the main activity to send data to the remote device */ public void write(byte[] bytes) < try < mmOutStream.write(bytes); >catch (IOException e) < >> /* Call this from the main activity to shutdown the connection */ public void cancel() < try < mmSocket.close(); >catch (IOException e) < >> > >
Transfer Bluetooth data
After you have successfully connected to a Bluetooth device, each one has a connected BluetoothSocket . You can now share information between devices. Using the BluetoothSocket , the general procedure to transfer data is as follows:
- Get the InputStream and OutputStream that handle transmissions through the socket using getInputStream() and getOutputStream() , respectively.
- Read and write data to the streams using read(byte[]) and write(byte[]) .
There are, of course, implementation details to consider. In particular, you should use a dedicated thread for reading from the stream and writing to it. This is important because both the read(byte[]) and write(byte[]) methods are blocking calls. The read(byte[]) method blocks until there is something to read from the stream. The write(byte[]) method doesn’t usually block, but it can block for flow control if the remote device isn’t calling read(byte[]) quickly enough and the intermediate buffers become full as a result. So, you should dedicate your main loop in the thread to reading from the InputStream . You can use a separate public method in the thread to initiate writes to the OutputStream .
Example
The following is an example of how you can transfer data between two devices connected over Bluetooth:
Kotlin
private const val TAG = "MY_APP_DEBUG_TAG" // Defines several constants used when transmitting messages between the // service and the UI. const val MESSAGE_READ: Int = 0 const val MESSAGE_WRITE: Int = 1 const val MESSAGE_TOAST: Int = 2 // . (Add other message types here as needed.) class MyBluetoothService( // handler that gets info from Bluetooth service private val handler: Handler) < private inner class ConnectedThread(private val mmSocket: BluetoothSocket) : Thread() < private val mmInStream: InputStream = mmSocket.inputStream private val mmOutStream: OutputStream = mmSocket.outputStream private val mmBuffer: ByteArray = ByteArray(1024) // mmBuffer store for the stream override fun run() < var numBytes: Int // bytes returned from read() // Keep listening to the InputStream until an exception occurs. while (true) < // Read from the InputStream. numBytes = try < mmInStream.read(mmBuffer) >catch (e: IOException) < Log.d(TAG, "Input stream was disconnected", e) break >// Send the obtained bytes to the UI activity. val readMsg = handler.obtainMessage( MESSAGE_READ, numBytes, -1, mmBuffer) readMsg.sendToTarget() > > // Call this from the main activity to send data to the remote device. fun write(bytes: ByteArray) < try < mmOutStream.write(bytes) >catch (e: IOException) < Log.e(TAG, "Error occurred when sending data", e) // Send a failure message back to the activity. val writeErrorMsg = handler.obtainMessage(MESSAGE_TOAST) val bundle = Bundle().apply < putString("toast", "Couldn't send data to the other device") >writeErrorMsg.data = bundle handler.sendMessage(writeErrorMsg) return > // Share the sent message with the UI activity. val writtenMsg = handler.obtainMessage( MESSAGE_WRITE, -1, -1, mmBuffer) writtenMsg.sendToTarget() > // Call this method from the main activity to shut down the connection. fun cancel() < try < mmSocket.close() >catch (e: IOException) < Log.e(TAG, "Could not close the connect socket", e) >> > >
Java
public class MyBluetoothService < private static final String TAG = "MY_APP_DEBUG_TAG"; private Handler handler; // handler that gets info from Bluetooth service // Defines several constants used when transmitting messages between the // service and the UI. private interface MessageConstants < public static final int MESSAGE_READ = 0; public static final int MESSAGE_WRITE = 1; public static final int MESSAGE_TOAST = 2; // . (Add other message types here as needed.) >private class ConnectedThread extends Thread < private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; private byte[] mmBuffer; // mmBuffer store for the stream public ConnectedThread(BluetoothSocket socket) < mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the input and output streams; using temp objects because // member streams are final. try < tmpIn = socket.getInputStream(); >catch (IOException e) < Log.e(TAG, "Error occurred when creating input stream", e); >try < tmpOut = socket.getOutputStream(); >catch (IOException e) < Log.e(TAG, "Error occurred when creating output stream", e); >mmInStream = tmpIn; mmOutStream = tmpOut; > public void run() < mmBuffer = new byte[1024]; int numBytes; // bytes returned from read() // Keep listening to the InputStream until an exception occurs. while (true) < try < // Read from the InputStream. numBytes = mmInStream.read(mmBuffer); // Send the obtained bytes to the UI activity. Message readMsg = handler.obtainMessage( MessageConstants.MESSAGE_READ, numBytes, -1, mmBuffer); readMsg.sendToTarget(); >catch (IOException e) < Log.d(TAG, "Input stream was disconnected", e); break; >> > // Call this from the main activity to send data to the remote device. public void write(byte[] bytes) < try < mmOutStream.write(bytes); // Share the sent message with the UI activity. Message writtenMsg = handler.obtainMessage( MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer); writtenMsg.sendToTarget(); >catch (IOException e) < Log.e(TAG, "Error occurred when sending data", e); // Send a failure message back to the activity. Message writeErrorMsg = handler.obtainMessage(MessageConstants.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString("toast", "Couldn't send data to the other device"); writeErrorMsg.setData(bundle); handler.sendMessage(writeErrorMsg); >> // Call this method from the main activity to shut down the connection. public void cancel() < try < mmSocket.close(); >catch (IOException e) < Log.e(TAG, "Could not close the connect socket", e); >> > >
After the constructor acquires the necessary streams, the thread waits for data to come through the InputStream . When read(byte[]) returns with data from the stream, the data is sent to the main activity using a member Handler from the parent class. The thread then waits for more bytes to be read from the InputStream .
To send outgoing data, you call the thread’s write() method from the main activity and pass in the bytes to be sent. This method calls write(byte[]) to send the data to the remote device. If an IOException is thrown when calling write(byte[]) , the thread sends a toast to the main activity, explaining to the user that the device couldn’t send the given bytes to the other (connected) device.
The thread’s cancel() method allows you to terminate the connection at any time by closing the BluetoothSocket . Always call this method when you’re done using the Bluetooth connection.
For a demonstration of using the Bluetooth APIs, see the Bluetooth Chat sample app on GitHub.
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2021-10-27 UTC.