안녕하세요

 

불루투스 chat 예제를 응용하여 블루투스 통신 앱을 만들고 있습니다.

 

그런데 문제는..

 

connected 함수에서 connectedTread 함수를 start 하니 예상치 못한 예러가 발생합니다.

 

이틀동안 이부분만 봐도 답이 안나오네요

 

한수만 가르쳐주세요 뭐가 문제 인지..

 

혹시다 다른데서 잘 못 된줄 알고, 계속 찾아봣는데 아무리 찾아도 답이 안나옵니다.

 

소스 코드 입니다.

 

public class BluetoothService{
 
 // Debugging
    private static final String TAG = "BluetoothChatService";
    private static final boolean D = true;

   
    // Name for the SDP record when creating server socket
    private static final String NAME = "BluetoothChat";

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

   
    // Member fields
    private final BluetoothAdapter mAdapter;
    private final Handler mHandler ;
    private AcceptThread mAcceptThread;
    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

    public BluetoothService(Context context, Handler handler) {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mState = STATE_NONE;
        mHandler = handler;
       
       
    }
   
   

    private synchronized void setState(int state) {
        if (D) Log.d(TAG, "setState() " + mState + " -> " + state);
        mState = state;

        // Give the new state to the Handler so the UI Activity can update
        mHandler.obtainMessage(btService.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
    }
    /* Return the current connection state. */
    public synchronized int getState() {
        return mState;
    }
   

    public synchronized void start() {
        if (D) Log.d(TAG, "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;
        }

        // Start the thread to listen on a BluetoothServerSocket
        if (mAcceptThread == null) {
            mAcceptThread = new AcceptThread();
            mAcceptThread.start();
           
            //////////// 이다음 함수 호출 하여 위치정보 및 문자 수신!!!
           
        }
        setState(STATE_LISTEN);
    }
   
    public synchronized void connect(BluetoothDevice device) {
        if (D) 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;}

        // Start the thread to connect with the given device
        mConnectThread = new ConnectThread(device);
        mConnectThread.start();
        setState(STATE_CONNECTING);
    }
    public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
        if (D) Log.d(TAG, "connected");
      
        Message msg1 = mHandler.obtainMessage(btService.MESSAGE_TOAST);
        Bundle bundle1= new Bundle();
        bundle1.putString(btService.TOAST, "connected : 함수 진입!! mConnectThread : " + mConnectThread);
        msg1.setData(bundle1);
        mHandler.sendMessage(msg1);
       
       
        try {
   Thread.sleep(5000);
  } catch (InterruptedException e1) {
   // TODO Auto-generated catch block
   e1.printStackTrace();
  }
        // If a connection was accepted
       
        // Cancel the thread that completed the connection
        // 연결을 완료 시 thread 취소
        if (mConnectThread != null) {
         mConnectThread.cancel();
         mConnectThread = null;
         
        }

        // Cancel any thread currently running a connection
        //현재 연결을 실행하는 스레드를 취소
        if (mConnectedThread != null) {
         mConnectedThread.cancel();
         mConnectedThread = null;
         
         
        }

        // Cancel the accept thread because we only want to connect to one device
        //하나의 디바이스 연결을 원하기 때문에 accept thread 취소
        if (mAcceptThread != null) {
         mAcceptThread.cancel();
         mAcceptThread = null;
         
        }
     
        // Start the thread to manage the connection and perform transmissions
        mConnectedThread = new ConnectedThread(socket);
        
        mConnectedThread.start(); /// 여기에서 문제 발생!!!!!!
        이것만 실행하면 앱이 예상치 못한 에러라고 말하며 죽습니다.
        //UI 활동에 다시 연결된 장치의 이름을 보내기
  
        Message msg = mHandler.obtainMessage(btService.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();
        bundle.putString(btService.DEVICE_NAME, device.getName());
        msg.setData(bundle);
        mHandler.sendMessage(msg);

        setState(STATE_CONNECTED);
    }

    public synchronized void stop() {
        if (D) Log.d(TAG, "stop");
       
        if (mConnectThread != null) {
         mConnectThread.cancel();
         mConnectThread = null;

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

    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);
    }
   
    private void connectionFailed() {
        setState(STATE_LISTEN);

        // Send a failure message back to the Activity
        Message msg = mHandler.obtainMessage(btService.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(btService.TOAST, "Unable to connect device");
        msg.setData(bundle);
        mHandler.sendMessage(msg);
    }

   
    private void connectionLost() {
        setState(STATE_LISTEN);

        // Send a failure message back to the Activity
        Message msg = mHandler.obtainMessage(btService.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(btService.TOAST, "Device connection was lost");
        msg.setData(bundle);
        mHandler.sendMessage(msg);
      
        // 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;}
       
        if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread.stop(); mAcceptThread = null;}
       
        mAcceptThread = new AcceptThread();
        mAcceptThread.start();
       
        setState(STATE_LISTEN);
       
    }

    private class AcceptThread extends Thread {
        // The local server socket
     
        private final BluetoothServerSocket mmServerSocket;
       
        public AcceptThread() {
            BluetoothServerSocket tmp = null;
     ///////////////////////////////////////////////////////////////////////////////////      
            Message msg = mHandler.obtainMessage(btService.MESSAGE_TOAST);
            Bundle bundle = new Bundle();
            bundle.putString(btService.TOAST, "AcceptThread 생성");
            msg.setData(bundle);
            mHandler.sendMessage(msg);
      ///////////////////////////////////////////////////////////////////////////////     
            // Create a new listening server socket
            //새로운 청취 서버 소켓을 만듭니다
            try {
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
            } catch (IOException e) {
                Log.e(TAG, "listen() failed", e);
            }
            mmServerSocket = tmp;
           
        }
       
        @Override
        public void run() {
         // TODO Auto-generated method stub
         super.run();
         
         if (D) Log.d(TAG, "BEGIN mAcceptThread" + this);
            setName("AcceptThread");
            BluetoothSocket socket = null;
///////////////////////////////////////////////////////////////////////////////////////////////
            Message msg = mHandler.obtainMessage(btService.MESSAGE_TOAST);
            Bundle bundle = new Bundle();
            bundle.putString(btService.TOAST, "AcceptThread 실행 (Start-run() 함수 발동!!");
            msg.setData(bundle);
            mHandler.sendMessage(msg);
//////////////////////////////////////////////////////////////////////////////////////////////
          
            // Listen to the server socket if we're not connected
            //우리가 연결되지 않은 경우 서버 소켓에 기다리기
            while (mState != STATE_CONNECTED) {
                try {
                    // This is a blocking call and will only return on a
                    // successful connection or an exception
                    socket = mmServerSocket.accept();
                } catch (Exception e) {
                    Log.e(TAG, "accept() failed", e);
                    break;
                }

                Message msg1 = mHandler.obtainMessage(btService.MESSAGE_TOAST);
             Bundle bundle1 = new Bundle();
             bundle1.putString(btService.TOAST, "socket : "+ socket.toString());
             msg1.setData(bundle1);
             mHandler.sendMessage(msg1);
             
             
             try {
     Thread.sleep(1000);
    } catch (InterruptedException e1) {
     // TODO Auto-generated catch block
     e1.printStackTrace();
    }
                // If a connection was accepted
               
             try{
                 if (socket != null) {
                  synchronized (BluetoothService.this) {
                   switch (mState) {
                   case STATE_LISTEN: // 지금 들어오는 연결 수신
                   case STATE_CONNECTING: // 지금 나가는 연결의 시작
                    // Situation normal. Start the connected thread.
                    //정상적인 상황. 연결된 스레드를 시작합니다.
                    connected(socket, socket.getRemoteDevice());
                    break;
                   case STATE_NONE: //
                   case STATE_CONNECTED: //이제 원격 장치에 연결
                            // Either not ready or already connected. Terminate new socket.
                         //어느 준비하거나 이미 연결되지 않았습니다. 새로운 소켓을 종료 할 수 있습니다.
                    try {
                     socket.close();
                    } catch (IOException e) {
                     Log.e(TAG, "Could not close unwanted socket", e);
                    }
                    break;
                   }
                  }
                 }  
                }catch(Exception ex){
                 
                }
            }
            if (D) Log.i(TAG, "END mAcceptThread");
        }
       

        public void cancel() {
            if (D) Log.d(TAG, "cancel " + this);
            try {
                mmServerSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of server failed", e);
            }
        }
    }

    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;
       
        public ConnectThread(BluetoothDevice device) {
   // TODO Auto-generated constructor stub
         mmDevice = device;
            BluetoothSocket tmp = null;

            // Get a BluetoothSocket for a connection with the
            // given BluetoothDevice
            try {
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) {
                Log.e(TAG, "create() failed", e);
            }
            mmSocket = tmp;
  }
       
   
        @Override
        public void run() {
         // TODO Auto-generated method stub
         super.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) {
                connectionFailed();
                // Close the socket
                try {
                    mmSocket.close();
                } catch (IOException e2) {
                    Log.e(TAG, "unable to close() socket during connection failure", e2);
                }
                // Start the service over to restart listening mode
                //듣기 모드를 다시 시작 서비스를 다시 시작
                BluetoothService.this.start();
                return;
            }

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

            // Start the connected thread
            //원격 블루투스 장치에 연결 되었을때 사용하는 스레드를 기동하는 메소드를 호출한다
            connected(mmSocket, mmDevice);
        }
        public void cancel(){
            try{
             mmSocket.close();
            }catch(IOException e){
             Log.e(TAG, "cloase() of connect socket failed ", e);
            }
        }
         
       

    }
   
    private class ConnectedThread extends Thread{
     private final BluetoothSocket mmSocket;
     private final InputStream mmInStream;
     private final OutputStream mmOutputStream;
     
     
     public ConnectedThread(BluetoothSocket socket) {
   // TODO Auto-generated constructor stub
      Log.d(TAG, "create ConnectedThread");
      mmSocket = socket;
      InputStream tmpIn = null;
      OutputStream tmpOut = null;
      
      try{
       tmpIn = socket.getInputStream();
       tmpOut = socket.getOutputStream();
       
     //  isConnected = true;
       
      }catch (IOException e){
       Log.e(TAG, "temp sockets not created", e);
      }
      
      mmInStream = tmpIn;
      mmOutputStream = tmpOut;
  }

     @Override
     public void run() {
      // TODO Auto-generated method stub
      super.run();
      
      Message msg1 = mHandler.obtainMessage(btService.MESSAGE_TOAST);
            Bundle bundle1= new Bundle();
            bundle1.putString(btService.TOAST, "run() : 함수 진입!!!!!!!!!!!!!!!!!!!  " );
            msg1.setData(bundle1);
            mHandler.sendMessage(msg1);
         
      
      
      byte[] buffer = new byte[1024];
      int bytes;
      
      while(true){
       try{
        
        bytes = mmInStream.read(buffer);       
        mHandler.obtainMessage(btService.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
       }catch(IOException e){
        Log.e(TAG, " Exception during write", e);
        connectionLost();
       }
      }
     }
     
     private void write(byte[] buffer) {
   // TODO Auto-generated method stub
      try{
       mmOutputStream.write(buffer);
       
       
       mHandler.obtainMessage(btService.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
      }catch(IOException e){
       Log.e(TAG, "Exception during write", e);
      }
  }
     
     private void cancel() {
   // TODO Auto-generated method stub
      try{
       mmSocket.close();
      }catch(IOException e){
       Log.e(TAG, "Close() of connect socket failed", e);
      }
  }
    }
   

}

 

앱이 서비스랑 같이 쓰고 있는데 서비스 부분은 올리지 않았습니다.

 

스레드 생성하는데 혹시 서비스에서 제약을 받을 수 있는지도 궁금합니다.

 

mConnectedThread = new ConnectedThread(socket);
        
        mConnectedThread.start(); /// 여기에서 문제 발생!!!!!!

 

일단 mConnectedThread 생성은 확실하게 되었는데

 

start가 되지 않아 mConnectedThread.run() 으로 해보니 run 함수는 호출이 되구요

 

아무래도 스레드가 생성 되지 않는것 같은데 원인을 알 수 있을까요?

 

ㅠㅠ 이부분만 해결 되면 끝인데; 원인을 찾을수가 없네요

 

답변기다리겠습니다.