2010-07-07 9 views
3

내 안드로이드를 블루투스 장치에 연결해야합니다. Google의 BluetoothChat 샘플을 사용합니다.블루투스 연결을 끊는 방법 (HTC Desire)

Google Nexus에서 연결을 설정했지만 연결이 끊어지기 때문에 문제가 발생했습니다. 해결 방법으로 연결을 두 번 시작해야합니다 (connectionLost() 참조).

이제 Nexus One과 HTC Desire에서도 잘 작동합니다.

제 문제는 응용 프로그램 종료시 연결 끊김입니다. Nexus에서 정상적으로 작동하지만 연결은 닫히지 만 HTC Desire에서는 작동하지 않습니다. 나는 소켓 close에 덧붙여 inputstream/outputstream close 함수를 추가한다. "stop()"함수를 살펴보십시오.

package xxx.yyy.zzz; 

import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.lang.reflect.Method; 
import java.util.UUID; 

import activities.Act_Main; 

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 android.util.Log; 

/** 
* This class does all the work for setting up and managing Bluetooth 
* connections with other devices. It has a thread that listens for 
* incoming connections, a thread for connecting with a device, and a 
* thread for performing data transmissions when connected. 
*/ 
public class BluetoothService { 
    // Debugging 
    private static final String TAG = "BluetoothService"; 
    private static final boolean D = true; 

    // Member fields 
    //private final BluetoothAdapter mAdapter; 
    private final Handler mHandler; 
    private ConnectThread mConnectThread; 
    private ConnectedThread mConnectedThread; 
    private int mState; 
    private String mBTAddress; 
    private boolean isStop = false; 

    // 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 Act_Main session. 
    * @param context The UI Activity Context 
    * @param handler A Handler to send messages back to the UI Activity 
    */ 
    public BluetoothService(Context context, Handler handler) 
    { 
     //mAdapter = BluetoothAdapter.getDefaultAdapter(); 
     mState = STATE_NONE; 
     mHandler = handler; 
    } 

    /** 
    * Set the current state of the connection 
    * @param state An integer defining the current connection state 
    */ 
    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(Act_Main.MESSAGE_STATE_CHANGE, state, -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(String BTAddress) 
    { 
     mBTAddress = BTAddress ; 

     // Get the BLuetoothDevice object 
     BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(BTAddress); 

     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); 
     isStop = false ; 
    } 

    /** 
    * 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) 
    { 
     if (D) Log.d(TAG, "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(Act_Main.MESSAGE_DEVICE_NAME); 
     Bundle bundle = new Bundle(); 
     bundle.putString(Act_Main.DEVICE_NAME, device.getName()); 
     msg.setData(bundle); 
     mHandler.sendMessage(msg); 

     setState(STATE_CONNECTED); 
    } 

    /** 
    * Stop all threads 
    */ 
    public synchronized void stop() 
    { 
     isStop = true ; 

     if (D) 
      Log.d(TAG, "stop"); 

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

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

     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) 
     { 
      Log.d(TAG, "BT_SEND_MESSAGE"); 

      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() 
    { 
     try 
     { 
      synchronized (this) 
      { 
       this.wait(3000); 
      } 
      connect(mBTAddress); 
     } 
     catch(InterruptedException ex) 
     { 
      Log.e(TAG, "WAIT_EXCEPTION:"+ ex.getMessage()); 
     } 
    } 

    /** 
    * Indicate that the connection was lost and notify the UI Activity. 
    */ 
    private void connectionLost() 
    { 
     if (!isStop) 
      connect(mBTAddress); 
    } 

    /** 
    * 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(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); 
      } 
      catch (Exception e) 
      { 
       Log.e(TAG, "create() failed", e); 
      } 
      mmSocket = tmp; 
     } 

     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) 
      { 
       connectionFailed(); 

       // Close the socket 
       try 
       { 
        mmSocket.close(); 
       } 
       catch (IOException e2) 
       { 
        Log.e(TAG, "unable to close() socket during connection failure", e2); 
       } 
       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, "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 BluetoothSocket mmSocket; 
     private InputStream mmInStream; 
     private 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; 
     } 

     public void run() 
     { 
      Log.i(TAG, "BEGIN mConnectedThread"); 
      byte[] buffer; 
      int bytes = 0; 

      // Keep listening to the InputStream while connected 
      while (true) 
      { 
       try 
       { 
        //Clear buffer 
        buffer = new byte[1024]; 

        // Read from the InputStream 
        bytes = mmInStream.read(buffer); 

        // Send the obtained bytes to the UI Activity 
        mHandler.obtainMessage(Act_Main.MESSAGE_READ, bytes, -1, buffer).sendToTarget(); 
       } 
       catch (IOException e) 
       { 
        //String bufferStr = new String(buffer, 0, buffer.length); 
        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); 
      } 
      catch (IOException e) 
      { 
       Log.e(TAG, "Exception during write", e); 
      } 
     } 

     public void cancel() 
     { 
      if (mmOutStream != null) 
      { 
       try {mmOutStream.close();} catch (Exception e) { Log.e(TAG, "close() of outputstream failed", e); } 
       mmOutStream = null; 
      } 

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

      if (mmSocket != null) 
      { 
       try {mmSocket.close();} catch (Exception e) { Log.e(TAG, "close() of connect socket failed", e); } 
       mmSocket = null; 
      } 
     } 
    } 
} 

미리 도움을 주셔서 감사합니다.

내가 지금이 글을 읽고

+0

사람이 예 내가 구글에서 싫어 자신의 프로 요 업데이트를 통해 고정 보인다 스트림을 읽어 연결을 할 때하지 말아야 할 그 모든 것을. 잠시 동안 (사실) 사용하는 것은 내가 싫어하는 것입니다. 나는 항상 while (! Thread.interrupted()) – JPM

답변

1

코드의 동기화에 대한 빠른 코멘트 :

connect() 방법에 synchronized 키워드를두고 있지만 연결 시간을 때, 오히려 connect()에서 스레드를 만드는 대신 스레드에서 connect() 전화 . 현재로서는 코드가 connect()의 연결 스레드에서 시작되어 동기화 목적을 상실합니다. (목적은 connect()에 요청을 동기화하여 복수 스레드가 동시에 connect을 시도 할 때 혼란스럽지 않게하는 것입니다.) 이로 인해 연결 문제가 발생할 수 있습니다.

나는 당신을 생각하고 내가 같은 문제가 발생했습니다 다음 HTC에 대한

Why can't HTC Droid running OTA 2.1 communicate with RFCOMM?

블루투스 연결 분리에 관한 참고 :

것은 정상적으로 때마다 연결을 해제해야합니다을 cancel() 방법을 사용하십시오.

+0

설명을 주셔서 감사합니다. Google에서 제공하는 소스 코드 ... 놀라운 일입니다. 그리고 HTC의 블루투스 버그가 너무 미쳤습니다 ... HTC와 관련된 뉴스가 있으면 알려주십시오. – Hrk

0

JJ : Bluetooth on 2.0+

사람 HTC의 욕망의 나쁜 구현에 대한 해결책습니까?

업데이트 : 예를 들어, 나는 아주 나쁜 해결 방법을했습니다. 응용 프로그램을 종료하면 프로세스가 종료됩니다.

ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 
am.restartPackage("com.example.package"); 

저는 여전히 더 깨끗한 솔루션을 기다리고 있습니다.

0

UPDATE : 그것은 HTC가 (안드로이드 2.2)

관련 문제