저번 글에서 블루투스 페어링 까지 알아 보았다.

 

그럼 이번엔 블루투스 사이의 연동부분을 알아보자. 이부분은 블루투스 챗 서비스에 너무너무 잘 나와있다.

 

그중 필요한 부분만 발췌하였다.

 

BluetoothClientConnect.java

 

package com.example.btclient;

 

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.UUID;

 

import android.bluetooth.BluetoothAdapter;

import android.bluetooth.BluetoothDevice;

import android.bluetooth.BluetoothSocket;

import android.content.Context;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

 

import com.example.btclient.util.Logger;

 

public class BluetoothClientConnect {

    // Unique UUID for this application

    private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");

    

    // Member fields

    private final BluetoothAdapter mBluetoothAdapter;

    private final Handler mHandler;

    private ConnectThread mConnectThread;

    private ConnectedThread mConnectedThread;

    private int mState;

 

    // 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

    

    /**

     * Constructor. Prepares a new BluetoothConnect session.

     *

     * @param context The UI Activity Context

     * @param handler A Handler to send messages back to the UI Activity

     */

    public BluetoothClientConnect(Context context, Handler handler) {

     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

     mHandler = handler;

        mState = STATE_NONE;

    }

    

    /**

     * Set the current state of the chat connection

     *

     * @param state An integer defining the current connection state

     */

    private synchronized void setState(int state) {

        Logger.print("setState() " + mState + " -> " + state);

        mState = state;

 

        // Give the new state to the Handler so the UI Activity can update

        mHandler.obtainMessage(BTClientMainActivity.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();

    }

    

    /**

     * Return the current connection state.

     */

    public synchronized int getState() {

        return mState;

    }

    

    /**

     * Start the chat service. Specifically start AcceptThread to begin a

     * session in listening (server) mode. Called by the Activity onResume()

     */

    public synchronized void start() {

     Logger.print("start...");

    

     // Cancel any thread attempting to make a connection

        if (mConnectThread != null) {

            mConnectThread.cancel();

            mConnectThread = null;

        }

 

        // Cancel any thread currently running a connection

        if (mConnectedThread != null) {

            mConnectedThread.cancel();

            mConnectedThread = null;

        }

 

        setState(STATE_LISTEN);

    }

    

    /**

     * Start the ConnectThread to initiate a connection to a remote device.

     *

     * @param device The BluetoothDevice to connect

     */

    public synchronized void connect(BluetoothDevice device) {

     Logger.print("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;

        }

 

        // Start the thread to connect with the given device

        mConnectThread = new ConnectThread(device);

        mConnectThread.start();

        setState(STATE_CONNECTING);

    }

    

    /**

     * 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) {

     Logger.print("connected");

 

        // 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(BTClientMainActivity.MESSAGE_DEVICE_NAME);

        Bundle bundle = new Bundle();

        bundle.putString(BTClientMainActivity.DEVICE_NAME, device.getName());

        msg.setData(bundle);

        mHandler.sendMessage(msg);

 

        setState(STATE_CONNECTED);

    }

    

    /**

     * Stop all threads

     */

    public synchronized void stop() {

     Logger.print("stop");

    

        if (mConnectThread != null) {

            mConnectThread.cancel();

            mConnectThread = null;

        }

        if (mConnectedThread != null) {

            mConnectedThread.cancel();

            mConnectedThread = null;

        }

 

        setState(STATE_NONE);

    }

    

    /**

     * 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() {

        setState(STATE_LISTEN);

 

        // Send a failure message back to the Activity

        Message msg = mHandler.obtainMessage(BTClientMainActivity.MESSAGE_TOAST);

        Bundle bundle = new Bundle();

        bundle.putString(BTClientMainActivity.TOAST, "Unable to connect device");

        msg.setData(bundle);

        mHandler.sendMessage(msg);

    }

    

    /**

     * Indicate that the connection was lost and notify the UI Activity.

     */

    private void connectionLost() {

        setState(STATE_LISTEN);

 

        // Send a failure message back to the Activity

        Message msg = mHandler.obtainMessage(BTClientMainActivity.MESSAGE_TOAST);

        Bundle bundle = new Bundle();

        bundle.putString(BTClientMainActivity.TOAST, "Device connection was lost");

        msg.setData(bundle);

        mHandler.sendMessage(msg);

    }

 

    /**

     * 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 mSocket;

        private final BluetoothDevice mDevice;

 

        public ConnectThread(BluetoothDevice device) {

            mDevice = device;

            BluetoothSocket tmp = null;

 

            // Get a BluetoothSocket for a connection with the

            // given BluetoothDevice

            try {

                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);

            } catch (IOException e) {

             Logger.print("create() failed : " + e.getMessage());

            }

            mSocket = tmp;

        }

 

        public void run() {

         Logger.print("BEGIN mConnectThread");

            setName("ConnectThread");

 

            // Always cancel discovery because it will slow down a connection

            mBluetoothAdapter.cancelDiscovery();

 

            // Make a connection to the BluetoothSocket

            try {

                // This is a blocking call and will only return on a

                // successful connection or an exception

                mSocket.connect();

            } catch (IOException e) {

                connectionFailed();

                // Close the socket

                try {

                    mSocket.close();

                } catch (IOException e2) {

                 Logger.print("unable to close() socket during connection failure : " + e2.getMessage());

                }

                // Start the service over to restart listening mode

                BluetoothClientConnect.this.start();

                return;

            }

 

            // Reset the ConnectThread because we're done

            synchronized (BluetoothClientConnect.this) {

                mConnectThread = null;

            }

 

            // Start the connected thread

            connected(mSocket, mDevice);

        }

 

        public void cancel() {

            try {

                mSocket.close();

            } catch (IOException e) {

             Logger.print("close() of connect socket failed : " + e.getMessage());

            }

        }

    }

 

    /**

     * 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 mSocket;

        private final InputStream mInStream;

        private final OutputStream mOutStream;

 

        public ConnectedThread(BluetoothSocket socket) {

         Logger.print("create ConnectedThread");

 

            mSocket = socket;

            InputStream tmpIn = null;

            OutputStream tmpOut = null;

 

            // Get the BluetoothSocket input and output streams

            try {

                tmpIn = socket.getInputStream();

                tmpOut = socket.getOutputStream();

            } catch (IOException e) {

             Logger.print("temp sockets not created : " + e.getMessage());

            }

 

            mInStream = tmpIn;

            mOutStream = tmpOut;

        }

 

        public void run() {

 

         Logger.print("BEGIN mConnectedThread");

            byte[] buffer = new byte[1024];

            int bytes;

 

            // Keep listening to the InputStream while connected

            while (true) {

                try {

                    // Read from the InputStream

                    bytes = mInStream.read(buffer);

 

                    // Send the obtained bytes to the UI Activity

                    mHandler.obtainMessage(BTClientMainActivity.MESSAGE_READ, bytes, -1, buffer).sendToTarget();

 

                } catch (IOException e) {

                 Logger.print("disconnected : " + e.getMessage());

                    connectionLost();

                    break;

                }

            }

        }

 

//        /**

//         * Write to the connected OutStream.

//         *

//         * @param buffer The bytes to write

//         */

        public void write(byte[] buffer) {

            try {

                mOutStream.write(buffer);

 

                // Share the sent message back to the UI Activity

                mHandler.obtainMessage(BTClientMainActivity.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();

            } catch (IOException e) {

             Logger.print("Exception during write : " + e.getMessage());

            }

        }

 

        public void cancel() {

            try {

                mSocket.close();

            } catch (IOException e) {

             Logger.print("close() of connect socket failed : " + e.getMessage());

            }

        }

    }

}


자바를 어느정도 읽을줄 아는 분이면 대충이해가 갈것이다.
여기에는 중요한 쓰레드가 두개가 나온다. ConnectThread와 ConnectedThread이다.

먼저 여기서 쓰레드를 사용한 이유는 메인 UI의 버벅거림을 주지 않기 위해서라는 것을 파악하고 넘어가자

ConnectThread 는 서버에 접속하는 쓰레드 이다. 
ConnectedThread 는 서버로 메시지를 전송 또는 서버에서 보낸 메시지를 받는 쓰레드 이다.

InputStream 과 OutputStream 을이용해서 서버와 메시지를 주고 받는다.

받은 메시지를 클라이언트 화면에 보여주기 위해서 Handler를 사용하였다.


by Invincible Cooler 2014. 10. 28. 11:14