Sending Images over Bluetooth in Android

12 May

Android provides the functionality of sending data over Bluetooth and there are not much of tutorials for sending data over Bluetooth. There is a sample chat application which sends messages to other Android phones over RFCOMM channels.  However if we want to send bigger data by modifying this chat application it doesn’t works (or didn’t worked for me well) and code in this chat application is humongous (though it also provides better functionality). I will try to make an application which sends images to other phones and while keeping the code small. This code can be modified to send different sorts of data or files.

On Android developer website there is a great deal of information on Bluetooth and it would be better to have a look at the bluetooth article before. Though we will revise some basic knowledge necessary for this tutorial. We will divide this application to two parts: a server which receives an image and a sender which sends an image by breaking it into bytes.

First of all we need to include the BLUETOOTH permission and if you want to include device discovery option (not included in tutorial) you will need BLUETOOTH_ADMIN permission as well. We will be using the UUID (Universally Unique Identifier) from sample bluetooth chat application.

First of all we will implement a server:

1. Call the listenUsingRfcommWithServiceRecord(String, UUID) method for BluetoothServerSocket.

2. Call accept() method on BluetoothServerSocket for listening to incoming connections.

3. After a successful connection the connection will be transferred to a BluetoothSocket.

4. From the connected BluetoothSocket, read the input stream from getInputStream.

5. The data will be read in the form of bytes, we will copy the bytes to a buffer.

6. Contrary to the small data transfer, we have to read all the data for showing the image on the server side.

7. Load the buffer to an ImageView.

8. The above steps will be performed in a class that extends a Thread because some of the steps are blocking calls.

Here is code for server

public class Sendingdata_serverActivity extends Activity {
 /** Called when the activity is first created. */
 private BluetoothAdapter mBluetoothAdapter = null;
 private static final UUID MY_UUID =
 UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
 private byte[] buffer = new byte[8192];
 private ImageView image;

 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
 image = (ImageView) findViewById(R.id.imageView1);

 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
 if (mBluetoothAdapter == null) {
 Toast.makeText(this,
 "Bluetooth is not available.",
 Toast.LENGTH_LONG).show();
 finish();
 return;
 }

if (!mBluetoothAdapter.isEnabled()) {
 Toast.makeText(this,
 "Please enable your BT and re-run this program.",
 Toast.LENGTH_LONG).show();
 finish();
 return;
 }
 AcceptData acceptData = new AcceptData();
 acceptData.start();
 Bitmap bm1 = BitmapFactory.decodeByteArray(buffer, 0, buffer.length);
 image.setImageBitmap(bm1);
 }

 class AcceptData extends Thread{
 private final BluetoothServerSocket mmServerSocket;
 private BluetoothSocket socket = null;
 private InputStream mmInStream;
 private String device;
 public AcceptData() {
 BluetoothServerSocket tmp = null;
 try {
 tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("Bluetooth", MY_UUID);
 } catch (IOException e) {
 //
 }
 mmServerSocket = tmp;
 try {
 socket = mmServerSocket.accept();
 } catch (IOException e) {
 //
 }
 device = socket.getRemoteDevice().getName();
 Toast.makeText(getBaseContext(), "Connected to " + device, Toast.LENGTH_SHORT).show();
 InputStream tmpIn = null;
 try {
 tmpIn = socket.getInputStream();
 } catch (IOException e) {
 //
 }
 mmInStream = tmpIn;
 int byteNo;
 try {
 byteNo = mmInStream.read(buffer);
 if (byteNo != -1) {
 //ensure DATAMAXSIZE Byte is read.
 int byteNo2 = byteNo;
 int bufferSize = 7340;
 while(byteNo2 != bufferSize){
 bufferSize = bufferSize - byteNo2;
 byteNo2 = mmInStream.read(buffer,byteNo,bufferSize);
 if(byteNo2 == -1){
 break;
 }
 byteNo = byteNo+byteNo2;
 }
 }
 if (socket != null) {
 try {
 mmServerSocket.close();
 } catch (IOException e) {
 //
 }
 }
 }
 catch (Exception e) {
 // TODO: handle exception
 }
}
}
}

Now to present the bytes as an image we will need an ImageView in our main.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="vertical" >
 <ImageView
 android:id="@+id/imageView1"
 android:layout_width="50px"
 android:layout_height="50px"
 />
</LinearLayout>

Now we are done with the server part which receives the data. For the sender part we will act as client which connects to the server and sends the data. For the client/sender we need to follow these steps:

1. Get the MAC address of the phone acting as a server.

2. Create a BluetoothSocket instance of BluetoothDevice while calling createRfcommSocketToServiceRecord(UUID).

3. Connect the BluetoothSocket.

4. Get the output stream channel associated with the connected BluetoothDevice.

5. Read the bytes from an image saved in drawable folder.

6. Write the bytes when a button is clicked.

Copy the image from following URL: https://kamrana.files.wordpress.com/2012/05/white.png and put it in the drawable folder of your project for this client/sender.

Code for Sender/Client:


public class SendingdataActivity extends Activity {
 /** Called when the activity is first created. */
 private BluetoothAdapter mBluetoothAdapter = null;
 static final UUID MY_UUID =
 UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
 static String address = "50:C3:00:00:00:00";

 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
 if (mBluetoothAdapter == null) {
 Toast.makeText(this,
 "Bluetooth is not available.",
 Toast.LENGTH_LONG).show();
 finish();
 return;
 }

if (!mBluetoothAdapter.isEnabled()) {
 Toast.makeText(this,
 "Please enable your BT and re-run this program.",
 Toast.LENGTH_LONG).show();
 finish();
 return;
 }
 final SendData sendData = new SendData();
 Button sendButton = (Button) findViewById(R.id.send);
 sendButton.setOnClickListener(new OnClickListener() {
 public void onClick(View view) {
 sendData.sendMessage();
 }
 });
 }

 class SendData extends Thread {
 private BluetoothDevice device = null;
 private BluetoothSocket btSocket = null;
 private OutputStream outStream = null;

 public SendData(){
 device = mBluetoothAdapter.getRemoteDevice(address);
 try
 {
 btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
 }
 catch (Exception e) {
 // TODO: handle exception
 }
 mBluetoothAdapter.cancelDiscovery();
 try {
 btSocket.connect();
 } catch (IOException e) {
 try {
 btSocket.close();
 } catch (IOException e2) {
 }
 }
 Toast.makeText(getBaseContext(), "Connected to " + device.getName(), Toast.LENGTH_SHORT).show();
 try {
 outStream = btSocket.getOutputStream();
 } catch (IOException e) {
 }
 }

 public void sendMessage()
 {
 try {
 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
 Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.white);
 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 bm.compress(Bitmap.CompressFormat.JPEG, 100,baos); //bm is the bitmap object
 byte[] b = baos.toByteArray();
 Toast.makeText(getBaseContext(), String.valueOf(b.length), Toast.LENGTH_SHORT).show();
 outStream.write(b);
 outStream.flush();
 } catch (IOException e) {
 }
 }
 }
 }

Here is main.xml for sender

</pre>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:gravity="center_vertical"
 android:orientation="vertical" >

 <Button
 android:id="@+id/send"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="Send"
 />

</LinearLayout>

Running the Application:

First run the server then after a second or two run the Sender. On the sender side you will get a Toast that you are connected to the other phone then press send button. There you go, you have tranferred the image, phewwww.

We can also send another image as for example we can use ic_launcher.png already present in the drawable folder but we have to change the BufferSize to 2691. BufferSize represents the array length or number of bytes the server is suppose to receive.

OK image size is small but you mess around with it just search for resizing bitmap on the internet.

t.

P.S. I believe all the code has been provided in this article. I don’t have the source code with me now as it got deleted, apologies for that.

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: