javaandroid

How to send/receive messages via bluetooth android studio


I am trying to create an app that allows a string to be sent from one Android phone to another. The code for this is provided below. However, it isn't working as I keep getting exceptions from the try catch piece of code under the pairDevice() section. Does anyone know why I might be getting this?

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.ParcelUuid;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Scanner;
import java.util.Set;

public class MainActivity extends AppCompatActivity {

    InputStream inStream;
    OutputStream outputStream;
    private static final int REQUEST_ENABLE_BT = 1;

    public void pairDevice() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new 
            Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);}

        Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
        if (pairedDevices.size() > 0) {
            Object[] devices = pairedDevices.toArray();
            BluetoothDevice device = (BluetoothDevice) devices[0];
            ParcelUuid[] uuid = device.getUuids();
            try {
                BluetoothSocket socket = device.createInsecureRfcommSocketToServiceRecord(uuid[0].getUuid());
                socket.connect();
                Toast.makeText(this, "Socket connected", Toast.LENGTH_LONG).show();
                outputStream = socket.getOutputStream();
                inStream = socket.getInputStream();
            } catch (IOException e) {
                Toast.makeText(this, "Exception found", Toast.LENGTH_LONG).show();
            }

        }
    }


public void SendMessage(View v) {
    EditText outMessage = (EditText) findViewById(R.id.editText);
    try {
        if (outputStream != null)
            outputStream.write(outMessage.toString().getBytes());
            TextView displayMessage = (TextView) findViewById(R.id.textView);
            Scanner s = new Scanner(inStream).useDelimiter("\\A");
            displayMessage.setText(s.hasNext() ? s.next() : "");
    } catch (IOException e) {/*Do nothing*/}
    Toast.makeText(this,"No output stream", Toast.LENGTH_LONG).show();
}





@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    pairDevice();
}

}


Solution

  • I have made few changes to your app:-

    Firstly, I shifted the code responsible for creating the Bluetooth connection to ConnectThread.

    2) Added AcceptThread responsible for listening incoming connections and ConnectedThread maintaining the BTConnection, Sending the data, and receiving incoming data through input/output streams respectively. 3) Created 2 buttons to start ConnectThread and AcceptThread.

    NOTE: Make sure both the devices are paired and the device that you are trying to connect to is at the top of the list(or just remove all the paired devices from both the devices and only pair the devices that you want to connect). Also, you must start the AcceptThread before ConnectThread

    MAINACTIVITY.JAVA

    public class MainActivity extends AppCompatActivity {
    
        private static final UUID MY_UUID_INSECURE =
                UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
    
        private static final int REQUEST_ENABLE_BT = 1;
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        private BluetoothDevice mmDevice;
        private UUID deviceUUID;
        ConnectedThread mConnectedThread;
        private Handler handler;
    
        String TAG = "MainActivity";
        EditText send_data;
        TextView view_data;
        StringBuilder messages;
    
    
    
    
    
    
        public void pairDevice(View v) {
    
            Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
            Log.e("MAinActivity", "" + pairedDevices.size() );
            if (pairedDevices.size() > 0) {
                Object[] devices = pairedDevices.toArray();
                BluetoothDevice device = (BluetoothDevice) devices[0];
                //ParcelUuid[] uuid = device.getUuids();
                Log.e("MAinActivity", "" + device );
                //Log.e("MAinActivity", "" + uuid)
    
                ConnectThread connect = new ConnectThread(device,MY_UUID_INSECURE);
                connect.start();
    
            }
        }
    
        private class ConnectThread extends Thread {
            private BluetoothSocket mmSocket;
    
            public ConnectThread(BluetoothDevice device, UUID uuid) {
                Log.d(TAG, "ConnectThread: started.");
                mmDevice = device;
                deviceUUID = uuid;
            }
    
            public void run(){
                BluetoothSocket tmp = null;
                Log.i(TAG, "RUN mConnectThread ");
    
                // Get a BluetoothSocket for a connection with the
                // given BluetoothDevice
                try {
                    Log.d(TAG, "ConnectThread: Trying to create InsecureRfcommSocket using UUID: "
                            +MY_UUID_INSECURE );
                    tmp = mmDevice.createRfcommSocketToServiceRecord(MY_UUID_INSECURE);
                } catch (IOException e) {
                    Log.e(TAG, "ConnectThread: Could not create InsecureRfcommSocket " + e.getMessage());
                }
    
                mmSocket = tmp;
    
                // Make a connection to the BluetoothSocket
    
                try {
                    // This is a blocking call and will only return on a
                    // successful connection or an exception
                    mmSocket.connect();
    
                } catch (IOException e) {
                    // Close the socket
                    try {
                        mmSocket.close();
                        Log.d(TAG, "run: Closed Socket.");
                    } catch (IOException e1) {
                        Log.e(TAG, "mConnectThread: run: Unable to close connection in socket " + e1.getMessage());
                    }
                    Log.d(TAG, "run: ConnectThread: Could not connect to UUID: " + MY_UUID_INSECURE );
                }
    
                //will talk about this in the 3rd video
                connected(mmSocket);
            }
            public void cancel() {
                try {
                    Log.d(TAG, "cancel: Closing Client Socket.");
                    mmSocket.close();
                } catch (IOException e) {
                    Log.e(TAG, "cancel: close() of mmSocket in Connectthread failed. " + e.getMessage());
                }
            }
        }
    
        private void connected(BluetoothSocket mmSocket) {
            Log.d(TAG, "connected: Starting.");
    
            // Start the thread to manage the connection and perform transmissions
            mConnectedThread = new ConnectedThread(mmSocket);
            mConnectedThread.start();
        }
    
        private class ConnectedThread extends Thread {
            private final BluetoothSocket mmSocket;
            private final InputStream mmInStream;
            private final OutputStream mmOutStream;
    
            public ConnectedThread(BluetoothSocket socket) {
                Log.d(TAG, "ConnectedThread: Starting.");
    
                mmSocket = socket;
                InputStream tmpIn = null;
                OutputStream tmpOut = null;
    
    
    
                try {
                    tmpIn = mmSocket.getInputStream();
                    tmpOut = mmSocket.getOutputStream();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
                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) {
                    // Read from the InputStream
                    try {
                        bytes = mmInStream.read(buffer);
                        final String incomingMessage = new String(buffer, 0, bytes);
                        Log.d(TAG, "InputStream: " + incomingMessage);
    
                        runOnUiThread(new Runnable() {
    
                            @Override
                            public void run() {
                                view_data.setText(incomingMessage);
                            }
                        });
    
    
                    } catch (IOException e) {
                        Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage() );
                        break;
                    }
                }
            }
    
    
            public void write(byte[] bytes) {
                String text = new String(bytes, Charset.defaultCharset());
                Log.d(TAG, "write: Writing to outputstream: " + text);
                try {
                    mmOutStream.write(bytes);
                } catch (IOException e) {
                    Log.e(TAG, "write: Error writing to output stream. " + e.getMessage() );
                }
            }
    
            /* Call this from the main activity to shutdown the connection */
            public void cancel() {
                try {
                    mmSocket.close();
                } catch (IOException e) { }
            }
        }
    
    
        public void SendMessage(View v) {
            byte[] bytes = send_data.getText().toString().getBytes(Charset.defaultCharset());
            mConnectedThread.write(bytes);
        }
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
    
            send_data =(EditText) findViewById(R.id.editText);
            view_data = (TextView) findViewById(R.id.textView);
    
            if (bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) {
                Intent enableBtIntent = new
                        Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            }
    
    
        }
    
        public void Start_Server(View view) {
    
            AcceptThread accept = new AcceptThread();
            accept.start();
    
        }
    
        private class AcceptThread extends Thread {
    
            // The local server socket
            private final BluetoothServerSocket mmServerSocket;
    
            public AcceptThread(){
                BluetoothServerSocket tmp = null ;
    
                // Create a new listening server socket
                try{
                    tmp = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("appname", MY_UUID_INSECURE);
    
                    Log.d(TAG, "AcceptThread: Setting up Server using: " + MY_UUID_INSECURE);
                }catch (IOException e){
                    Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() );
                }
    
                mmServerSocket = tmp;
            }
    
            public void run(){
                Log.d(TAG, "run: AcceptThread Running.");
    
                BluetoothSocket socket = null;
    
                try{
                    // This is a blocking call and will only return on a
                    // successful connection or an exception
                    Log.d(TAG, "run: RFCOM server socket start.....");
    
                    socket = mmServerSocket.accept();
    
                    Log.d(TAG, "run: RFCOM server socket accepted connection.");
    
                }catch (IOException e){
                    Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() );
                }
    
                //talk about this is in the 3rd
                if(socket != null){
                    connected(socket);
                }
    
                Log.i(TAG, "END mAcceptThread ");
            }
    
            public void cancel() {
                Log.d(TAG, "cancel: Canceling AcceptThread.");
                try {
                    mmServerSocket.close();
                } catch (IOException e) {
                    Log.e(TAG, "cancel: Close of AcceptThread ServerSocket failed. " + e.getMessage() );
                }
            }
    
        }
    

    ACTIVITY_MAIN.XML

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.hpi5.bluethoothshot.MainActivity"
        tools:layout_editor_absoluteY="81dp"
        tools:layout_editor_absoluteX="0dp">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            android:id="@+id/textView"
            tools:layout_constraintTop_creator="1"
            tools:layout_constraintRight_creator="1"
            app:layout_constraintRight_toRightOf="parent"
            android:layout_marginTop="58dp"
            tools:layout_constraintLeft_creator="1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <EditText
            android:id="@+id/editText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="10"
            android:inputType="textPersonName"
            android:text="Name"
            tools:layout_constraintTop_creator="1"
            tools:layout_constraintRight_creator="1"
            app:layout_constraintRight_toRightOf="parent"
            android:layout_marginTop="153dp"
            tools:layout_constraintLeft_creator="1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:onClick="SendMessage"
            tools:layout_constraintTop_creator="1"
            tools:layout_constraintRight_creator="1"
            app:layout_constraintRight_toRightOf="parent"
            android:layout_marginTop="22dp"
            app:layout_constraintTop_toBottomOf="@+id/editText"
            tools:layout_constraintLeft_creator="1"
            app:layout_constraintLeft_toLeftOf="parent" />
    
        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Server"
            android:onClick="Start_Server"
            android:layout_marginEnd="53dp"
            tools:layout_constraintRight_creator="1"
            tools:layout_constraintBottom_creator="1"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            android:layout_marginBottom="84dp" />
    
        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="ConnectionREq"
            android:onClick="pairDevice"
            android:layout_marginStart="34dp"
            tools:layout_constraintTop_creator="1"
            tools:layout_constraintBottom_creator="1"
            app:layout_constraintBottom_toBottomOf="@+id/button2"
            tools:layout_constraintLeft_creator="1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="@+id/button2"
            android:layout_marginLeft="30dp"
            app:layout_constraintVertical_bias="0.0" />
    
    </android.support.constraint.ConstraintLayout>