0

In my application that in the beginning i only manage a single Activity for connect and exchange data with OBD2 via bluetooth i add a navigation drawer and more tasks that some of them still use bluetooth connection.

For not to weigh bluetooth for each Fragment i close the Socket connection and delete the instantiation of the class MyBluetoothService.java posted below:

public class MyBluetoothService {


    // Debugging
    private static final String TAG = "MyBluetoothService";

    // Unique UUID for this application
    private static final UUID MY_UUID_SECURE =
            UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
            //UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");

    // Member fields
    private final BluetoothAdapter mAdapter;
    private final Handler mHandler;
    //Threads
    private ConnectThread mConnectThread;
    private ConnectedThread mConnectedThread;
    private ManageDataThread mManageThread;
    //States UI
    private int mState;
    private int mNewState;

    //Readed Data, raw and formatted
    private String rawData = null;
    private String formattedMessage = null;

    //Stopper for the write array and w8 response
    private boolean canGo = true;

    private ArrayList<String> commandArray = null;

    //private BluetoothSocket mmSocket = null;
    //private BluetoothDevice mmDevice = null;


    // Constants that indicate the current connection state
    public static final int STATE_NONE = 0;       // we're doing nothing
    public static final int STATE_LISTEN = 1;     // now listening for incoming connections
    public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
    public static final int STATE_CONNECTED = 3;  // now connected to a remote device

    public static final int STATE_WAIT_RESPONSE = 4; //now wait the response of message send
    public static final int STATE_NO_MSG_SEND = 5; //now don't wait for responce
    /**
     * Constructor. Prepares a new BluetoothChat session.
     *
     * @param context The UI Activity Context
     * @param handler A Handler to send messages back to the UI Activity
     */
    public MyBluetoothService(Context context, Handler handler, ArrayList<String> commands) {

        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mState = STATE_NONE;
        mNewState = mState;
        mHandler = handler;
        //TODO gestire i comandi direttamente da questa classe con uno sharedArray
        commandArray = commands;

    }



    /**
     * Update UI title according to the current state of the chat connection
     */
    private synchronized void updateUserInterfaceTitle() {
        mState = getState();
        Log.d(TAG, "updateUserInterfaceTitle() " + mNewState + " -> " + mState);
        mNewState = mState;

        // Give the new state to the Handler so the UI Activity can update
        mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, mNewState, -1).sendToTarget();
    }

    /**
     * Return the current connection state.
     */
    public synchronized int getState() {
        return mState;
    }


    /**
     * Start the ConnectThread to initiate a connection to a remote device.
     *
     * @param device The BluetoothDevice to connect
     */
    public synchronized void connect(BluetoothDevice device) {

        Log.d(TAG, "connect to: " + device);

        // Cancel any thread attempting to make a connection
        if (mState == STATE_CONNECTING) {
            if (mConnectThread != null) {
                mConnectThread.cancel();
                mConnectThread = null;
            }
        }

        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }

        // Cancel any thread currently managing connections
        if (mManageThread != null) {
            mManageThread.cancel();
            mManageThread = null;
        }


        // Start the thread to connect with the given device
        mConnectThread = new ConnectThread(device);
        mConnectThread.start();
        // Update UI title
        updateUserInterfaceTitle();
    }

    /**
     * Start the ConnectedThread to begin managing a Bluetooth connection
     *
     * @param socket The BluetoothSocket on which the connection was made
     * @param device The BluetoothDevice that has been connected
     */
    public synchronized void connected(BluetoothSocket socket, BluetoothDevice
            device) {
        Log.d(TAG, "manage, Socket Type:");

        // Cancel the thread that completed the connection
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }

        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }

        // Start the thread to manage the connection and perform transmissions
        mConnectedThread = new ConnectedThread(socket);
        mConnectedThread.start();

        // Send the name of the connected device back to the UI Activity
        Message msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();
        bundle.putString(Constants.DEVICE_NAME, device.getName());
        msg.setData(bundle);
        mHandler.sendMessage(msg);
        // Update UI title
        updateUserInterfaceTitle();
    }

    private synchronized void manage(BluetoothSocket socket, BluetoothDevice device) {
        Log.d(TAG, "Manage Socket");

        // Cancel the thread that completed the connection
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }

        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        // Cancel any thread currently managing connections
        if (mManageThread != null) {
            mManageThread.cancel();
            mManageThread = null;
        }

        canGo = true;
        // Start the thread to manage the connection and perform transmissions
        mManageThread = new ManageDataThread(socket);
        mManageThread.start();

        // Send the name of the connected device back to the UI Activity
        Message msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();
        bundle.putString(Constants.DEVICE_NAME, device.getName());
        msg.setData(bundle);
        mHandler.sendMessage(msg);
        // Update UI title
        updateUserInterfaceTitle();

    }


    /**
     * Stop all threads
     */
    public synchronized void stop() {
        Log.d(TAG, "stop");

        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }

        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }

        if (mManageThread != null) {
            canGo = false;
            mManageThread.cancel();
            mManageThread = null;
        }

        mState = STATE_NONE;
        // Update UI title
        updateUserInterfaceTitle();
    }

    /**
     * Write to the ConnectedThread in an unsynchronized manner
     *
     * @param out The bytes to write
     * @see ConnectedThread#write(byte[])
     */
    public void write(byte[] out) {
        // Create temporary object
        ConnectedThread r;
        // Synchronize a copy of the ConnectedThread
        synchronized (this) {
            if (mState != STATE_CONNECTED) return;
            r = mConnectedThread;
        }
        // Perform the write unsynchronized
        r.write(out);
    }

    /**
     * Indicate that the connection attempt failed and notify the UI Activity.
     */
    private void connectionFailed() {
        // Send a failure message back to the Activity
        Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(Constants.TOAST, "Unable to connect device");
        msg.setData(bundle);
        mHandler.sendMessage(msg);

        mState = STATE_NONE;
        // Update UI title
        updateUserInterfaceTitle();

        // Start the service over to restart listening mode
        MyBluetoothService.this.stop();
    }

    /**
     * Indicate that the connection was lost and notify the UI Activity.
     */
    private void connectionLost() {
        // Send a failure message back to the Activity
        Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(Constants.TOAST, "Device connection was lost");
        msg.setData(bundle);
        mHandler.sendMessage(msg);

        mState = STATE_NONE;
        // Update UI title
        updateUserInterfaceTitle();

        // Start the service over to restart listening mode
        //MyBluetoothService.this.start();
    }


    /**
     * This thread runs while attempting to make an outgoing connection
     * with a device. It runs straight through; the connection either
     * succeeds or fails.
     */
    private class ConnectThread extends Thread {

        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {
            mmDevice = device;
            BluetoothSocket tmp = null;


            // Get a BluetoothSocket for a connection with the
            // given BluetoothDevice
            try {
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE);

            } catch (IOException e) {
                Log.e(TAG, "Socket Type: create() failed", e);
            }
            mmSocket = tmp;
            mState = STATE_CONNECTING;
        }

        public void run() {
            Log.i(TAG, "BEGIN mConnectThread");
            setName("ConnectThread");

            // Always cancel discovery because it will slow down a connection
            mAdapter.cancelDiscovery();

            // 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();
                } catch (IOException e2) {
                    Log.e(TAG, "unable to close() socket during connection failure", e2);
                }
                connectionFailed();
                return;
            }

            // Reset the ConnectThread because we're done
            synchronized (MyBluetoothService.this) {
                mConnectThread = null;
            }

            // Start the connected thread
            //connected(mmSocket, mmDevice);
            manage(mmSocket, mmDevice);
            Log.d(TAG, "mmSocket: " + mmSocket);
            Log.d(TAG, "mmDevice: " + mmDevice);

        }

        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }

    /**
     * This thread runs during a connection with a remote device.
     * It handles all incoming and outgoing transmissions.
     */
    private class ConnectedThread extends Thread {

        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket) {
            Log.d(TAG, "create ConnectedThread: ");
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the BluetoothSocket input and output streams
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "temp sockets not created", e);
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
            mState = STATE_CONNECTED;
        }

        public void run() {

            Log.i(TAG, "BEGIN mConnectedThread");
            byte[] buffer = new byte[1024];
            int bytes;

            // Keep listening to the InputStream while connected
            while (mState == STATE_CONNECTED) {
                try {
                    // Read from the InputStream
                    bytes = mmInStream.read(buffer);

                    //TODO devo gestire l'arrivo di bytes
                    ObdCommand obc = new ObdCommand();
                    obc.readResult(mmInStream);

                    formattedMessage = obc.getResult();
                    //buffer = (byte) obc.getBuffer();

                    // Send the obtained bytes to the UI Activity
                    mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, formattedMessage)
                            .sendToTarget();

                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);
                    connectionLost();
                    break;
                }
            }
        }

        /**
         * Write to the connected OutStream.
         *
         * @param buffer The bytes to write
         */
        public void write(byte[] buffer) {
            try {
                mmOutStream.write(buffer);

                // Share the sent message back to the UI Activity
                mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer)
                        .sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "Exception during write", e);
            }
        }

        public void cancel() {

            if (mmInStream != null){
                try {
                    mmInStream.close();
                } catch (Exception e) {
                    Log.e(TAG, "close() of InStream socket failed", e);
                }
            }
            if (mmOutStream != null){
                try {
                    mmOutStream.close();
                } catch (Exception e) {
                    Log.e(TAG, "close() of OutStream socket failed", e);
                }
            }

            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }

    /** Thread che controlla la connessione e lo scambio continuo di messaggi con il
     *  dispositivo OBD connesso ...
     */
    //TODO
    public class ManageDataThread extends Thread {

        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
        private boolean wait_response = false;
        private String typeCommand;

        public ManageDataThread(BluetoothSocket socket) {
            Log.d(TAG, "create ManageDataThread: ");

            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the BluetoothSocket input and output streams
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "temp sockets not created", e);
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
            mState = STATE_CONNECTED;

        }

        public void run() {

            ObdCommand obc = new ObdCommand();

            while(canGo) {
                for (final String command : commandArray) {

                    byte[] send = command.getBytes();
                    write(send); //Setta la wait_response come true
                    //mState = STATE_WAIT_RESPONSE;

                    byte[] buffer = new byte[1024];
                    int bytes;

                    // Keep listening to the InputStream while connected
                    while (wait_response) {
                        try {
                            // Read from the InputStream
                            bytes = mmInStream.read(buffer);

                            obc.readResult(mmInStream);

                            //formattedMessage = obc.getResult();
                            formattedMessage = obc.getCalculatedResult();
                            //Ritorno la ripologia di comando
                            typeCommand = obc.getCommandType();
                            //buffer = (byte) obc.getBuffer();

                            // Send the obtained bytes to the UI Activity
                            /*mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, formattedMessage)
                                    .sendToTarget();*/

                            mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, typeCommand
                                    + ""
                                    + formattedMessage)
                                    .sendToTarget();

                            wait_response = false;

                        } catch (IOException e) {
                            Log.e(TAG, "disconnected", e);
                            connectionLost();
                            break;
                        }
                    }


                }

                try {
                    ManageDataThread.sleep(400);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }



        }

        /**
         * Write to the connected OutStream.
         *
         * @param buffer The bytes to write
         */
        public void write(byte[] buffer) {
            try {
                mmOutStream.write(buffer);

                // Share the sent message back to the UI Activity
                mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer)
                        .sendToTarget();
                wait_response = true;
            } catch (IOException e) {
                Log.e(TAG, "Exception during write", e);
                canGo = false;
            }
        }

        public void cancel() {
            try {
                canGo = false;
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }


    }

With this class i manage the connection like the BluetoothChatSimple example project.

But in my second fragment i need to connect again to the obd2 and take some particular data. This code is very articulate, there is some better way to do that?

Something that when i change Fragment just stop data exchange from obd and phone but the phone still connected with the obd so in another Fragment i can't send and receive different data by from different Fragments...

PS: I use the manageDataThread for data exchange with obd and get formatted results from hex.

Dario
  • 732
  • 7
  • 30
  • dont know if it s smart thing but why don't you make your BT connection as a singleton class and call try to connect or check if its connected whenever you want without make an instance of for each class? – mohsen_og Nov 08 '17 at 09:26
  • Can you post an answere with some example pls? Or some ideologic schema? – Dario Nov 09 '17 at 22:30
  • Sorry I don't access any computers therefore wrote it as comment. Anyway, just google for singleton! let me describe at least: you make a singleton class for your BT connection and any related functions. singleton as it name says can be initiated only once. This can be done by making the default constructor and copy constructor private. Now you can call this singleton and initiate it once (probably connect to BT as well) and on every onCreate check the connection. if not connected connect it again. – mohsen_og Nov 10 '17 at 09:42
  • Also there are some complains saying singleton is not safe in android. Unfortunately I dont know android very well. – mohsen_og Nov 10 '17 at 09:44
  • also read this article it might help as well https://medium.com/@programmerr47/singletons-in-android-63ddf972a7e7 – mohsen_og Nov 10 '17 at 10:09

0 Answers0